sendfile이 빈 stdin에서 작동하지 않습니다.

sendfile이 빈 stdin에서 작동하지 않습니다.

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에만stdinstdin실제로파이프, 블록 장치 등이 아닌 파일입니다.

나는 그것을 확인하기 위해 간단한 프로그램을 직접 작성했습니다.

#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

관련 정보