Ubuntu 14.04デスクトップ版では、Linuxカーネルモジュールを使用していくつかのシステムコールを接続しようとしています。
ところでフックwrite(unsigned int fd, const char __user *buf, size_t count)
してfilenameに戻してみると、ノーチラスにコピーして貼り付けるfd
ときにこのフォルダにwriteが呼び出されないことがわかりました。しかし、使用すると呼び出され、ファイル名が正確に 。/home/user/1.txt
/home/user/folder/
cp /home/user/1.txt /home/user/folder
write
/home/user/folder/1.txt
フックも試しましたが、pwrite
ノーチラスを使用してファイルを貼り付けても呼び出しは検出されません。
write
もしそうなら、ターゲットがシステムコールを呼び出さないとき、Nutilusはどのようにファイルを特定のフォルダにコピーして貼り付けますか?
答え1
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
カーネルとユーザースペースの間でデータをコピーすることなく、s間でデータを転送できるようにsplice(2)
Nautilusによって使用されます。一端にパイプが必要なfd
ため、Nautilusは入力ファイル記述子と出力ファイル記述子を持つパイプを作成します。ソースファイルとターゲットファイルを開いてパイプを作成した後、Nautilusはソースファイルのデータをパイプの入力として読み取るために使用され、2番目はパイプのデータを出力ファイルに書き込むために使用されます。この方法には、通常の方法と同様に、カーネルからユーザーへ、ユーザーからカーネルへのデータ変換は含まれません。man 2 splice
38
37
splice()
splice()
read()
write()
この動作はNautilusに固有のものではなく、Nautilusが使用するライブラリ(glib)に固有のものです。のように見えるこれは splice() 呼び出しです。Nautilusがglibの使用を観察しました。g_file_copy()これは順番に呼び出されます。file_copy_fallback()->splice_stream_with_progress()->do_splice()。