非空stdin的strace
输出:
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 +++
空stdin的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
发布于 2022-11-27 05:19:34
这似乎是sendfile
调用的预期行为。让我引用Linus Torvalds的例子:
sendfile()仅适用于使用页面缓存的东西。EINVAL基本上是sendfile的一种说法:“我会回到做read+write,所以您最好自己在用户空间中做,因为这样可能会更有效”。(https://yarchive.net/comp/linux/sendfile.html)
因此,只有当内核知道sendfile
实际上是一个文件,而不是管道、阻塞设备或其他任何东西时,stdin
才能使用stdin
。
我自己写了一个简单的程序来检查它:
#include
#include
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
https://unix.stackexchange.com/questions/550149
复制相似问题