Ubuntu

nautilus 粘貼文件時不呼叫寫入系統呼叫

  • November 24, 2018

我正在嘗試在 Ubuntu 14.04 桌面版上使用 linux 核心模組來掛鉤一些系統呼叫。

但是,當我hookwrite(unsigned int fd, const char __user *buf, size_t count)並變成fdfilename時,我發現當我在nautilus中複製/home/user/1.txt粘貼到/home/user/folder/時,在這個文件夾中沒有呼叫write。但是,如果我使用cp /home/user/1.txt /home/user/folder,我可以注意到write被呼叫並且文件名是/home/user/folder/1.txt.

我也嘗試過鉤子pwrite,但在使用 nautilus 粘貼文件時仍然沒有檢測到呼叫它。

write那麼,當目標上沒有呼叫系統呼叫時,nautilus 如何復製文件並粘貼到特定文件夾?

看起來 Nautilus 使用不同的方法進行優化。

假設我有一個/ntest/testfile包含 45 個字節的測試文件:

Lorem ipsum dolor sit amet
Leroooy Jeeenkins

我想把它移到目錄/ntest2中。為了追踪 Nautilus 到底做了什麼,我可以像這樣啟動它(實際上,我做了多次啟動,限制不那麼嚴格,但這是一個好的開始):

strace -f -P '/ntest/testfile' -P '/ntest2/testfile' -qq nautilus

從本質上講,以下摘錄解釋了會發生什麼(請注意,pipe2()上面的命令沒有擷取呼叫 - 我根據其他跟踪會話插入了它):

openat(AT_FDCWD, "/ntest/testfile", O_RDONLY) = 35
openat(AT_FDCWD, "/ntest2/testfile", O_WRONLY|O_CREAT|O_EXCL, 0644) = 36
pipe2([37, 38], O_CLOEXEC)  = 0
stat("/ntest2/testfile", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
splice(35, [0], 38, NULL, 1048576, SPLICE_F_MORE) = 45
splice(37, NULL, 36, [0], 45, SPLICE_F_MORE) = 45
close(35)                   = 0
close(36)                   = 0

Nautilus 使用splice(2)它允許在fds 之間傳輸一些數據,而無需在核心和使用者空間之間複製它。因為man 2 splice要求一端是管道,所以 Nautilus 創建了一個帶有輸入文件描述符38和輸出文件描述符的管道37。在打開源文件和目標文件並創建管道後,Nautilus 使用splice()從源文件讀取數據到管道的輸入;然後第二個splice()用於將此管道中的數據寫入輸出文件。read()這種方法不像普通方法那樣涉及核心到使用者和使用者到核心的數據轉換write()

請注意,此行為並非特定於 Nautilus,而是特定於它使用的庫 (glib)。看起來這是我們觀察到的 splice() 呼叫,因為 Nautilus 使用 glib 的g_file_copy()反過來呼叫file_copy_fallback() -> splice_stream_with_progress() -> do_splice()

引用自:https://unix.stackexchange.com/questions/483623