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