Я скорее смущен с целью этих трех файлов. Если мое понимание корректно, stdin
файл, в котором программа пишет в ее запросы для выполнения задачи в процессе, stdout
файл, в который ядро пишет свой вывод, и процесс, запрашивающий это, получает доступ к информации от, и stderr
файл, в который вводятся все исключения. При открытии этих файлов, чтобы проверить, происходят ли они на самом деле, я нашел, что ничто, кажется, не предлагает так!
То, что я хотел бы знать, - то, что точно является целью этих файлов, абсолютно dumbed вниз отвечают на очень небольшом количестве технического жаргона!
Стандартный ввод - это дескриптор файла , который ваш процесс читает, чтобы получить от вас информацию.
Стандартный вывод - ваш процесс записывает обычную информацию в этот дескриптор файла.
Стандартная ошибка - ваш процесс записывает информацию об ошибке в этот дескриптор файла.
Это настолько глупо, насколько я могу это сделать: -)
Конечно, это в основном условно. Если хотите, ничто не мешает вам записывать информацию об ошибках в стандартный вывод. Вы даже можете полностью закрыть три дескриптора файлов и открыть свои собственные файлы для ввода-вывода.
Когда ваш процесс запускается, у него уже должны быть открыты эти дескрипторы, и он может просто читать и / или писать в них.
По умолчанию они, вероятно, подключены к вашему терминальному устройству (например, / dev / tty
), но оболочки позволят вам установить соединения между этими дескрипторами и определенными файлами и / или устройствами (или даже конвейеры для других процессов) до запуска вашего процесса (некоторые из возможных манипуляций довольно умны).
Пример:
my_prog <inputfile 2>errorfile | grep XYZ
, который:
my_prog
. файл ввода
как стандартный ввод (дескриптор файла 0). файл ошибок
как стандартную ошибку (дескриптор файла 2). grep
. my_prog
к стандартному вводу grep
.По поводу вашего комментария:
Когда я открываю эти файлы в папке / dev, почему я никогда не вижу результат работы запущенного процесса?
Это потому, что это не обычные файлы. Хотя UNIX представляет все как файл где-то в файловой системе, это не делает это так на самых низких уровнях. Большинство файлов в иерархии / dev
являются либо символьными, либо блочными устройствами, фактически драйверами устройства. У них нет размера, но есть старший и младший номер устройства.
Когда вы открываете их, вы подключаетесь к драйверу устройства, а не к физическому файлу, и драйвер устройства достаточно умен, чтобы знать, что отдельные процессы должны обрабатываться отдельно.
То же самое верно и для файловой системы Linux / proc
. Это не настоящие файлы, а просто жестко контролируемые шлюзы к информации ядра.
Правильнее было бы сказать, что stdin
, stdout
и stderr
скорее являются «потоками ввода-вывода»).
чем файлы. Как вы заметили, эти объекты не живут в файловой системе. Но
Философия Unix в том, что касается ввода-вывода, - это «все является файлом».На практике,
это действительно означает, что вы можете использовать одни и те же библиотечные функции и интерфейсы ( printf
,
scanf
, read
, write
, select
и т. Д.), Не беспокоясь о том, будет ли поток ввода-вывода
подключен к клавиатуре, файлу на диске, сокету, каналу или какой-либо другой абстракции ввода-вывода.
Большинству программ необходимо читать ввод, записывать вывод и регистрировать ошибки, поэтому stdin
, stdout
,
и stderr
предопределены для вас для удобства программирования. Это только
соглашение, и операционная система не обеспечивает его соблюдение.
Боюсь, что ваше понимание совершенно обратное. :)
Думайте о "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. Я решил не усложнять и использовать более простые функции, но все же подумал, что вы должны знать альтернативы. :)
Читает ввод через консоль (например, ввод с клавиатуры). Используется в Си со scanf
scanf(<formatstring>,<pointer to storage> ...);
Производит вывод на консоль. Используется в C с printf
printf(<string>, <values to print> ...);
Выводит на консоль сообщение об ошибке. Используется в Си с 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>
.