Web

Что это — stdin, stdout и stderr?

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

 

Ответ 1

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

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

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

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

my_prog <inputfile 2>errorfile | grep XYZ

 Который делает следующее:

  1. создает процесс my_prog.

  2. открывает inputfile в качестве стандартного ввода (файл-хэндл 0).

  3. открывает errorfile в качестве стандартной ошибки (файл-хэндл 2).

  4. создает другой процесс для grep.

  5. присоединяет стандартный вывод my_prog к стандартному вводу grep.

В ответ на ваш вопрос:

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

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

 

Ответ 2

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

 

Ответ 3

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

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

«Стандартный ввод» используется, когда файл должен читать ввод, используя fread или fgets, или getchar. Любой из этих файлов может быть легко перенаправлен из оболочки, например, так:

cat /etc/passwd > /tmp/out     # перенаправить стандартный вывод cat в /tmp/foo

cat /nonexistant 2> /tmp/err   # перенаправить стандартную ошибку cat в /tmp/error

cat < /etc/passwd                    # перенаправить стандартный ввод cat в /etc/passwd

 Или так:

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

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

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

 

Ответ 4

Я думаю, что люди, говорящие, что stderr должен использоваться только для сообщений об ошибках, вводят в заблуждение.

Он также должен использоваться для информативных сообщений, которые предназначены для пользователя, выполняющего команду, а не для потенциальных потребителей данных (например, если вы запускаете shell pipe, соединяющий несколько команд, вы не хотите, чтобы информативные сообщения типа «получен элемент 30 из 42424» появлялись на stdout, так как они запутают потребителя, но вы все же можете захотеть, чтобы пользователь их увидел).

Смотрите здесь историческое обоснование:

«Все программы помещали диагностику на стандартный вывод. Это всегда вызывало проблемы, когда вывод перенаправлялся в file, но становилось невыносимым, когда вывод посылался ничего не подозревающему процессу. Тем не менее, не желая нарушать простоту модели «стандартный ввод-стандартный вывод», люди терпели такое положение дел до v6. Вскоре после этого Деннис Ричи разрубил гордиев узел, введя стандартную ошибку file. Этого было недостаточно. В конвейерах диагностика могла исходить от любой из нескольких одновременно выполняющихся программ. Диагностика должна была идентифицировать сама себя».

 

Ответ 5

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

 

Схожие статьи

Web

Проблемы при загрузке нескольких изображений с получением имени папки в базе данных

Информационная архитектура сайта: основы для начинающих разработчиков
Web

Информационная архитектура сайта: основы для начинающих разработчиков

Web

Функция PHP для генерации UUID v4

Web

Как заставить PHP перестать заменять символы «.» в массивах $_GET или $_POST

×