Перепутанный stdin, stdout и stderr?

Я скорее смущен с целью этих трех файлов. Если мое понимание корректно, stdin файл, в котором программа пишет в ее запросы для выполнения задачи в процессе, stdout файл, в который ядро пишет свой вывод, и процесс, запрашивающий это, получает доступ к информации от, и stderr файл, в который вводятся все исключения. При открытии этих файлов, чтобы проверить, происходят ли они на самом деле, я нашел, что ничто, кажется, не предлагает так!

То, что я хотел бы знать, - то, что точно является целью этих файлов, абсолютно dumbed вниз отвечают на очень небольшом количестве технического жаргона!

198
задан Jonathan Leffler 6 August 2018 в 09:26
поделиться

4 ответа

Стандартный ввод - это дескриптор файла , который ваш процесс читает, чтобы получить от вас информацию.

Стандартный вывод - ваш процесс записывает обычную информацию в этот дескриптор файла.

Стандартная ошибка - ваш процесс записывает информацию об ошибке в этот дескриптор файла.

Это настолько глупо, насколько я могу это сделать: -)

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

Когда ваш процесс запускается, у него уже должны быть открыты эти дескрипторы, и он может просто читать и / или писать в них.

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

Пример:

my_prog <inputfile 2>errorfile | grep XYZ

, который:

  • создаст процесс для my_prog .
  • откройте файл ввода как стандартный ввод (дескриптор файла 0).
  • откройте файл ошибок как стандартную ошибку (дескриптор файла 2).
  • создать еще один процесс для grep .
  • присоедините стандартный вывод my_prog к стандартному вводу grep .

По поводу вашего комментария:

Когда я открываю эти файлы в папке / dev, почему я никогда не вижу результат работы запущенного процесса?

Это потому, что это не обычные файлы. Хотя UNIX представляет все как файл где-то в файловой системе, это не делает это так на самых низких уровнях. Большинство файлов в иерархии / dev являются либо символьными, либо блочными устройствами, фактически драйверами устройства. У них нет размера, но есть старший и младший номер устройства.

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

То же самое верно и для файловой системы Linux / proc . Это не настоящие файлы, а просто жестко контролируемые шлюзы к информации ядра.

220
ответ дан 23 November 2019 в 05:12
поделиться

Правильнее было бы сказать, что stdin , stdout и stderr скорее являются «потоками ввода-вывода»). чем файлы. Как вы заметили, эти объекты не живут в файловой системе. Но Философия Unix в том, что касается ввода-вывода, - это «все является файлом».На практике, это действительно означает, что вы можете использовать одни и те же библиотечные функции и интерфейсы ( printf , scanf , read , write , select и т. Д.), Не беспокоясь о том, будет ли поток ввода-вывода подключен к клавиатуре, файлу на диске, сокету, каналу или какой-либо другой абстракции ввода-вывода.

Большинству программ необходимо читать ввод, записывать вывод и регистрировать ошибки, поэтому stdin , stdout , и stderr предопределены для вас для удобства программирования. Это только соглашение, и операционная система не обеспечивает его соблюдение.

53
ответ дан 23 November 2019 в 05:12
поделиться

Боюсь, что ваше понимание совершенно обратное. :)

Думайте о "standard in", "standard out" и "standard error" с точки зрения программы, а не с точки зрения ядра.

Когда программе нужно напечатать вывод, она обычно печатает в "standard out". Программа обычно печатает вывод на стандартный выход с помощью printf, который печатает ТОЛЬКО на стандартный выход.

Когда программе нужно вывести информацию об ошибках (не обязательно исключения, это конструкция языка программирования, введенная на гораздо более высоком уровне), она обычно печатает в "стандартную ошибку". Обычно это делается с помощью fprintf, которая принимает поток файлов для использования при печати. Файловым потоком может быть любой файл, открытый для записи: стандартный выход, стандартная ошибка или любой другой файл, открытый с помощью fopen или fdopen.

"Стандартный вход" используется, когда файлу нужно прочитать входные данные, используя fread или fgets, или getchar.

Любой из этих файлов может быть легко перенаправлен из оболочки, например, так:

cat /etc/passwd > /tmp/out     # redirect cat's standard out to /tmp/foo
cat /nonexistant 2> /tmp/err   # redirect cat's standard error to /tmp/error
cat < /etc/passwd              # redirect cat's standard input to /etc/passwd

Или, вся энчилада:

cat < /etc/passwd > /tmp/out 2> /tmp/err

Есть две важные оговорки: Во-первых, "стандартный вход", "стандартный выход" и "стандартная ошибка" - это просто соглашение. Это очень сильная конвенция, но это всего лишь соглашение о том, что очень приятно иметь возможность запускать такие программы, как: grep echo /etc/services | awk '{print $2;}' | sort и иметь стандартные выходы каждой программы, подключенные к стандартному входу следующей программы в конвейере.

Во-вторых, я привел стандартные функции ISO C для работы с файловыми потоками (объекты FILE *) - на уровне ядра это все файловые дескрипторы (ссылки на файловую таблицу int) и операции гораздо более низкого уровня, такие как read и write, которые не делают счастливой буферизации функций ISO C. Я решил не усложнять и использовать более простые функции, но все же подумал, что вы должны знать альтернативы. :)

.
22
ответ дан 23 November 2019 в 05:12
поделиться

stdin

Читает ввод через консоль (например, ввод с клавиатуры). Используется в Си со scanf

scanf(<formatstring>,<pointer to storage> ...);

stdout

Производит вывод на консоль. Используется в C с printf

printf(<string>, <values to print> ...);

stderr

Выводит на консоль сообщение об ошибке. Используется в Си с fprintf

fprintf(stderr, <string>, <values to print> ...);

Перенаправление

Источник stdin может быть перенаправлен. Например, вместо ввода с клавиатуры он может быть получен из файла (echo < file.txt ) или другой программы ( ps | grep ).

Направления для stdout и stderr также могут быть перенаправлены. Например, stdout может быть перенаправлен в файл: ls . > ls-output.txt, в этом случае вывод будет записан в файл ls-output.txt. Stderr может быть перенаправлен с помощью 2>.

8
ответ дан 23 November 2019 в 05:12
поделиться
Другие вопросы по тегам:

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