Как оболочка / init создает потоки stdio?

Не используйте регулярные выражения для синтаксического анализа HTML , тем более что с Perl это легче сделать Правильно.Например:

#!/usr/bin/env perl

use strict;
use warnings;

use HTML::LinkExtor;

my ( @web, $fn, $p );

sub cb {
    my ( undef, %links ) = @_;
    push @web, values %links;
}

$p = HTML::LinkExtor->new( \&cb );
while ( $fn = shift ) {
    $p->parse_file($fn);
    $p->eof;
}

print "$_\n" for (@web);

2
14.01.2020, 21:47
3 ответа

На самом деле это 3 вопроса. Немедленно удалите # 2, потому что программа неверна:

    while ((fd = open("sample.txt", O_RDWR) > 0)) {

вы, вероятно, имели в виду

    while ((fd = open("sample.txt", O_RDWR)) > 0) {

с неправильно размещенными круглыми скобками, вы проверяете только, если fd больше нуля (что, поскольку файловые дескрипторы 0, 1 и 2 открыты, что, вероятно, хорошее предположение).

Для №1: вызов open (в случае успеха) определен для возврата отдельных файловых дескрипторов. Если устройство не может быть повторно открыто, open вернет -1 .

Для №3: конечно, это соглашение , но также и стандарт POSIX . В других системах использовались другие соглашения, включая наличие четвертого открытого потока для каждой программы.

Дополнительная литература: Использование среды Aegis (июль 1988 г.)
См. Стр. 6-9, где говорится, что в домене / ОС Apollo была ошибка , вход и ** выход *

1
27.01.2020, 22:04

Нет, код не проверяет дескрипторы, он их фактически открывает. Не давая пока никаких дескрипторов. Каждое открытие будет давать новый дескриптор файла, т.е. 0,1,2,3. Код обрывается при достижении fd 3, оставляя открытыми от 0 до 2.

Каждый файловый дескриптор - это просто указатель на некоторое место в некотором файле. Поэтому нет никакой проблемы в том, чтобы иметь более одного дескриптора для одного и того же файла.

Если ваша тестовая программа выдает один и тот же fd для разных вызовов open, это означает, что в ней есть ошибка. Пожалуйста, покажите код.

Да, существует строгое соглашение о fd от 0 до 2. Если какой-то код хочет печатать на stdout, он на самом деле печатает на fd 1. Нет никакого способа "сопоставить" stdout с чем-то другим.

1
27.01.2020, 22:04

1) Если система поддерживает открытие одного и того же файла из нескольких процессов одновременно, то почему бы не разрешить одному процессу тоже открывать несколько раз? Поскольку файловые дескрипторы наследуются, в любом случае вы можете получить один и тот же файл дважды в одном и том же процессе, то есть если он унаследован один раз и один раз будет открыт самим процессом. Проверка того, какие файлы были открыты процессом, и возврат ссылки на более ранний - это дополнительная работа.

Также возникает вопрос, используют ли разные части процесса один и тот же файл одновременно. Скажем, библиотека использует какой-то файл конфигурации одновременно с основной программой. Дескриптор файла привязан к режиму доступа и положению указателя файла. Если бы существовала только одна их копия, происходили бы странные вещи. Кроме того, если файл был открыт дважды (с одним и тем же fd), что должно произойти, когда он закроется? Может быть еще один уровень подсчета ссылок, чтобы решить, когда действительно закрыть файл, но это не поможет с другими проблемами.


2) Зависит от вашего кода. Умный язык (то есть не C) может пересчитать переменную, содержащую открытый файл, и закрыть его непосредственно перед повторным открытием файла. Сложно сказать, не увидев кода.

Но небольшая проверка, дважды открывающая один и тот же файл для одной и той же переменной в Perl, приводит к тому же номеру FD:

perl -e 'open F, "test.txt"; printf "%d ", fileno(F); open F, "test.txt"; printf "%d\n", fileno(F)'
3 3

Запуск его в strace показывает, что файл закрывается непосредственно перед повторным открытием.

С двумя разными переменными мы получаем два номера FD:

perl -e 'open F, "test.txt"; printf "%d ", fileno(F); open G, "test.txt"; printf "%d\n", fileno(G)'
3 4

3) Технически можно сказать, что стандартные номера файлов - это соглашение. Соглашение, закрепленное в POSIX и стандарте ISO C :

При запуске программы должны быть предопределены три потока, и их не нужно открывать явно: стандартный ввод (для чтения обычного ввода), стандартный вывод ( для записи обычного вывода) и стандартной ошибки (для записи диагностического вывода).

Но в любом случае существует соглашение о том, что программу можно запускать без них, не обращая внимания на ядро. Или нет: читая спецификацию для вызовов exec , кажется, разрешено реализации, чтобы открыть что-то для вас :

Если файловый дескриптор 0, 1 или 2 в противном случае был бы закрыт после успешного вызова одной из функций семейства exec, реализации могут открыть неуказанный файл для файлового дескриптора в новом образе процесса.

(Вы, конечно, можете закрыть их в самой программе.)

Если вы сделаете так, чтобы они не были при запуске, совместимость выбрасывается:

Если стандартная утилита или соответствующее приложение выполняется с файловый дескриптор 0 не открыт для чтения или файловый дескриптор 1 или 2 не открыт для записи, среда, в которой выполняется утилита или приложение, считается несоответствующей, и, следовательно, утилита или приложение могут вести себя не так, как описано в этом стандарте .

В справочных страницах Linux это довольно практично :

В качестве общего принципа ни одна переносимая программа, будь то привилегированная или нет, не может предположить, что эти три файловые дескрипторы останутся закрытыми при вызове execve ().

1
27.01.2020, 22:04

Теги

Похожие вопросы