Когда программа запускается, принимает ли она файловые дескрипторы 0, 1 и 2 для stdin, stdout и stderr по умолчанию? И не будут ли вызовы API, такие как open(...), socket(...), возвращать 0, 1 и 2, поскольку эти значения уже приняты? Есть ли случай, когда open(...) или socket(...) вернут 0, 1 или 2. И 0, 1 и 2 не связаны с stdin, stdout и stderr.
Возможно ли, что дескриптор файла linux 0 1 2 не для stdin, stdout и stderr?
- Как я ответил, ваш вопрос не имеет большого смысла. файловый дескриптор 0 всегда является стандартным. 13.03.2014
Ответы:
На уровне файлового дескриптора stdin определяется как файловый дескриптор 0, stdout определяется как файловый дескриптор 1; а stderr определяется как файловый дескриптор 2. См. это.
Даже если ваша программа или оболочка- изменятся (например, перенаправление с помощью dup2(2 )) что такое файловый дескриптор 0, он всегда остается stdin (поскольку по определению STDIN_FILENO
равен 0).
Конечно, stdin может быть каналом, сокетом или файлом (не терминалом). Вы можете проверить с помощью isatty(3), если это tty и/или используйте fstat(2) для получения информации о состоянии на нем.
Системные вызовы типа open(2) или pipe(2) или socket(2) может дать, например STDIN_FILENO
(т.е. 0), если этот файловый дескриптор свободен (например, потому что он был закрыть(2)-d раньше). Но когда это происходит, это по-прежнему stdin по определению.
Конечно, в stdio(3) поток FILE
stdin немного сложнее. Ваша программа может fclose(3), freopen(3), fdopen(3) ...
Вероятно, ядро устанавливает файловые дескрипторы stdin, stdout и stderr на консоль при волшебном запуске /sbin/init
в качестве первого процесса. суп>
#P1#
#P2# #P3##P4#
#P5#
#P6##P7#
#P8#close(0); close(1); close(2); open(...); /* this open will return 0 if success */
dup()
или dup2()
. 13.03.2014 Хотя пара ответов уже существовала, но я не нашел их достаточно информативными, чтобы объяснить всю историю.
Поскольку я пошел дальше и исследовал больше, я добавляю свои выводы.
Всякий раз, когда процесс запускается, запись о запущенном процессе добавляется в каталог /proc/<pid>
. Это место, где хранятся все данные, связанные с процессом. Кроме того, при запуске процесса ядро выделяет процессу 3 файловых дескриптора для связи с тремя потоками данных, называемыми stdin
, stdout
и stderr
.
ядро linux использует алгоритм, всегда создающий FD с наименьшим возможным целочисленным значением, поэтому эти потоки данных отображаются на числа 0
, 1
и 2
.
Так как это не что иное, как ссылки на поток, и мы можем закрыть поток. Можно легко вызвать close(<fd>)
, в нашем случае close(1)
, чтобы закрыть файловый дескриптор.
при выполнении ls -l /proc/<pid>/fd/
мы видим только 2 FD, перечисленных там 0
и 2
.
Если мы сейчас выполним вызов open()
, ядро создаст новый FD для сопоставления этой новой ссылки на файл, и поскольку ядро использует алгоритм поиска с наименьшим целым числом, оно подберет целочисленное значение 1
.
Итак, теперь новый созданный FD указывает на файл, который мы открыли (используя системный вызов open()
)
Любая передача данных, которая происходит сейчас, осуществляется не через поток данных по умолчанию, который был связан ранее, а через новый файл, который мы открыли.
Так что да, мы можем сопоставить FD 0
, 1
или 2
с любым файлом и не обязательно stdin
, stdout
или stderr