Почему у / proc / self / fd / 0 нет бит записи в последовательном сеансе перед запуском оболочки?

Я наткнулся на программу, которая использует очень старую версию библиотеки linenoise . Все write() выполняются для STDIN_FILENO , например:

 write(STDIN_FILENO,prompt,plen) 

write не выполняется с -1 и errno устанавливается в EBADF . Я написал программу C, которая запускается в конце /etc/init.d/rcS которая, в свою очередь, выполняется Busybox init при загрузке системы до Busybox init интерактивного sh . Программа C перечисляет каталог /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 не имеет бит бит, и я думаю, что поэтому 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 . Почему это происходит?

  • Как разрешить пользователю OpenLDAP записывать данные в точку монтирования SSHFS?
  • Как определить, записаны ли данные на диск или кэшированы?
  • warning: Файловая система, похоже, смонтирована только для чтения
  • Отправка сообщения от одного пользователя терминала другому пользователю
  • Почему Debian предпочитает временный файл, заменяющий оригинал на изменение байтов в исходном файле?
  • One Solution collect form web for “Почему у / proc / self / fd / 0 нет бит записи в последовательном сеансе перед запуском оболочки?”

    Потому что вы можете иметь несколько терминальных устройств.

    Поэтому getty вызывается с ttyS0 специально, как параметр. Поэтому он использует свой собственный код для инициализации всех FD. Это происходит, по-другому, с кодом ядра, который открывает /dev/console для init . Можно догадаться, что getty открывает tty один раз O_RDWR , а затем дублирует FD.

    Я вижу одну очевидную причину, по которой этот код работает. agetty также можно вызвать с помощью значения stdin. Поэтому всегда использование dup() – это простейшая реализация.

    Я не уверен, почему этот вариант был поддержан. Он не обязательно используется или поддерживается в стандартной системе V inittab . Он, похоже, соответствует более старым подходам, используемым в BSD , где init передает терминальное устройство в качестве открытого FD вместо параметра. Более старый подход заключается в инициализации всех FD ( ссылка , обратите внимание только на 2 FDs, поскольку stderr был добавлен в следующую версию ).

    Поскольку вопрос был отредактирован, чтобы указать busybox, и был указан cttyhack, очевидное объяснение в случае busybox – «он сохраняет код меньше». Это было также движущей особенностью исторического кода unix.

    Linux и Unix - лучшая ОС в мире.