쉘이 시작되기 전에 /proc/self/fd/0에 직렬 세션에 쓰기 가능한 비트가 없는 이유는 무엇입니까?

쉘이 시작되기 전에 /proc/self/fd/0에 직렬 세션에 쓰기 가능한 비트가 없는 이유는 무엇입니까?

아주 오래된 버전을 사용하고 있는 프로그램을 발견했습니다라인 노이즈도서관. 다음과 같이 모든 write()작업이 완료되었습니다 STDIN_FILENO.

write(STDIN_FILENO,prompt,plen)

write실패하고 -1을 반환하며 errno로 설정됩니다 EBADF. 대화식으로 시작하기 전에 시스템이 시작될 때 순차적으로 실행되는 C 프로그램을 작성했습니다 /etc/init.d/rcS. C 프로그램은 디렉토리를 나열하고 출력은 다음과 같습니다.Busybox initsh/proc/self/fd

l-wx------    1 root     root          64 Jan  1 00:00 2 -> /dev/console
l-wx------    1 root     root          64 Jan  1 00:00 1 -> /dev/console
lr-x------    1 root     root          64 Jan  1 00:00 0 -> /dev/console

보시다시피 0 비트가 w설정되지 않았으므로 이것이 실패하는 것 같습니다 write. 그러나 sh일반 쉘이 시작된 후:

lrwx------    1 root     root          64 Jan  1 00:00 2 -> /dev/ttyS0
lrwx------    1 root     root          64 Jan  1 00:00 1 -> /dev/ttyS0
lrwx------    1 root     root          64 Jan  1 00:00 0 -> /dev/ttyS0

이제 0이 w설정되었습니다. 왜 이런 일이 발생합니까?

답변1

여러 개의 터미널 장치를 가질 수 있기 때문입니다.

따라서 getty구체적으로 매개변수라고 합니다. ttyS0따라서 자체 코드를 사용하여 모든 FD를 초기화합니다. 이는 tty를 한 번 연 /dev/console다음 FD 를 참조하는 것과 같습니다 .initgettyO_RDWRdup

분명한 이유가 보이네요암호다음과 같이 작동합니다. stdin을 사용하여 호출 agetty할 수도 있습니다 . -따라서 항상 사용하는 것이 dup()가장 간단한 구현입니다.

이 옵션이 왜 지원되는지 잘 모르겠습니다. 표준 시스템 V는 반드시 이를 사용하거나 지원하지는 않습니다 inittab. 와 일치하는 것 같다BSD에서 사용되는 이전 방법여기서 init터미널 장치는 매개변수 대신 열린 FD로 전달됩니다. 기존 방식은 init모든 FD를 초기화하는 것이었습니다(협회stderr, 다음 버전에 추가된 2개의 FD를 참고하세요 ).

busybox를 지정하도록 질문을 편집했고 cttyhack이 언급되었으므로 busybox의 경우 분명한 설명은 "코드를 더 작게 만듭니다"입니다. 이는 또한 역사적인 Unix 코드의 주요 특징이기도 합니다.

관련 정보