Смутно о stdin, stdout и stderr?

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

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

Ответ 1

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

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

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

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

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

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

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

Пример:

my_prog <inputfile 2>errorfile | grep XYZ

который будет:

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

Ваш комментарий:

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

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

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

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

Ответ 2

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

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

Ответ 3

В качестве дополнения к ответам, приведенным выше, ниже приводится сводная информация о перенаправлениях: Redirections cheatsheet

РЕДАКТИРОВАТЬ: эта графика не совсем правильно, но я не уверен, почему...

На рисунке написано, что 2> & 1 имеет тот же эффект, что и &> однако

ls Documents ABC > dirlist 2>&1
#does not give the same output as 
ls Documents ABC > dirlist &>

Ответ 4

Я боюсь, что ваше понимание полностью назад.:)

Подумайте о "стандартном", "стандартном" и "стандартной ошибке" с точки зрения программы, а не в перспективе ядра.

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

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

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

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

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

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

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

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

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

Ответ 5

STDIN

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

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

STDOUT

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

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

STDERR

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

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

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

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

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

Ответ 6

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

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

Смотрите это для исторического обоснования:

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

Ответ 7

Использование ps -aux показывает текущие процессы, все из которых перечислены в /proc/as/proc/ (pid)/, вызывая cat/proc/(pid)/fd/0, он печатает все, что находится в я думаю, стандартный выход этого процесса. Так что, возможно,

/proc/(pid)/fd/0 - Стандартный выходной файл
/proc/ (pid)/fd/1 - Стандартный входной файл
/proc/ (pid)/fd/2 - Стандартный файл ошибок

например my terminal window

Но он работал только хорошо для /bin/ bash, другие процессы вообще ничего не имели в 0, но у многих были ошибки, записанные в 2

Ответ 8

Чтобы получить достоверную информацию об этих файлах, ознакомьтесь с страницами man, запустите команду на своем терминале.

$ man stdout 

Но для простого ответа каждый файл предназначен для:

stdout для потока

stdin для ввода потока

stderr для печати ошибок или сообщений журнала.

Каждая программа unix имеет каждый из этих потоков.

Ответ 9

stderr не будет выполнять буферизацию IO Cache, поэтому, если нашему приложению необходимо распечатать важную информацию о сообщении (некоторые ошибки, исключения) для консоли или использовать ее в качестве источника использования, чтобы использовать общую информацию о журнале, поскольку она использует буферизацию IO Cache, есть вероятность, что перед тем, как писать наши сообщения в приложение, может закрыть, оставив комплекс отладки

Ответ 10

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

https://www.mkssoftware.com/docs/man5/stdio.5.asp