strace
空でないstdinの出力:
execve("./cat", ["./cat"], 0x7fff610af090 /* 37 vars */) = 0
sendfile(1, 0, NULL, 1048576) = 4
sendfile(1, 0, NULL, 1048576) = 0
close(0) = 0
exit(0) = ?
+++ exited with 0 +++
strace
空の標準入力として出力:
execve("./cat", ["./cat"], 0x7fff610af090 /* 37 vars */) = 0
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
sendfile(1, 0, NULL, 1048576) = -1 EINVAL (Invalid argument)
...
uname -a
:5.3.8-arch1-1 #1 SMP PREEMPT @1572357769 x86_64 GNU/Linux
答え1
sendfile
これは予想される通話動作のようです。 Linus Torvaldsの言葉を引用します。
sendfile() は、意図的にページキャッシュを使用するコンテンツに対してのみ機能します。 EINVAL は基本的に sendfile の表現方式です。 「私は読んで書くことをやっているので、あなたは自分のスペースで自分でやるのが本当に効率的かもしれません。
(https://yarchive.net/comp/linux/sendfile.html)
したがって、カーネルがこれが何であるかを知っている場合にsendfile
のみstdin
stdin
実際にパイプ、ブロックデバイスなどではないファイルです。
私はそれを確認するために簡単なプログラムを自分で書いた。
#include <stdio.h>
#include <sys/sendfile.h>
int main() {
sendfile(fileno(stdout), fileno(stdin), NULL, 8);
perror("sendfile failed");
}
さまざまなリダイレクトを使用して実行すると、sendfile
入力が通常のファイル(空であるかどうかにかかわらず)に直接バインドされている場合にのみ呼び出しが成功することがわかります。
$ ./sendfile-test
sendfile failed: Invalid argument
$ ./sendfile-test < empty.txt
sendfile failed: Success
$ ./sendfile-test < non-empty.txt
(...)
sendfile failed: Success
$ ./sendfile-test < /dev/null
sendfile failed: Invalid argument
$ cat empty.txt | ./sendfile-test
sendfile failed: Invalid argument
$ cat non-empty.txt | ./sendfile-test
sendfile failed: Invalid argument
$ cat /dev/null | ./sendfile-test
sendfile failed: Invalid argument