Книга: Программирование для Linux. Профессиональный подход
2.1.4. Стандартный ввод-вывод
2.1.4. Стандартный ввод-вывод
В стандартной библиотеке языка С определены готовые потоки ввода и вывода (stdin
и stdout
соответственно). Они используются функциями scanf()
, printf()
и целым рядом других библиотечных функций. Согласно идеологии UNIX, стандартные потоки можно перенаправлять. Это позволяет образовывать цепочки программ, связанных посредством каналов (конкретный синтаксис перенаправления потоков и работы с каналами можно узнать в документации к интерпретатору команд).
Есть также стандартный поток ошибок: stderr
. Программы должны направлять предупреждающие сообщения и сообщения об ошибках в него, а не в поток stdout
. Это позволяет отделять обычные выводные данные от разного рода служебных сообщений. К примеру, стандартный поток вывода можно направить в файл, а сообщения об ошибках, по-прежнему отображать на консоли. Запись в поток stderr
осуществляется с помощью функции fprintf()
:
fprintf(stderr, ("Error: ..."));
Все три стандартных потока доступны низкоуровневым функциям ввода-вывода (read()
, write()
и т.д.) через дескрипторы файлов. В частности, поток stdin
имеет дескриптор 0, stdout
— 1, a stderr
— 2.
При вызове программы иногда требуется одновременно перенаправить потоки вывода и ошибок в файл или канал. Синтаксис подобной операции зависит от используемого интерпретатора команд. В интерпретаторах семейства Bourne shell (включая bash
, который по умолчанию установлен в большинстве дистрибутивов Linux) это делается так:
% program > output_file.txt 2>&1
% program 2>&1 | filter
Запись 2>&1
означает, что файл с дескриптором 2 (stderr
) объединяется с файле имеющим дескриптор 1 (stdout
). Обратите внимание на то, что эта запись должна идти после операции перенаправления в файл (первый пример), но перед операцией перенаправления в канал (второй пример).
Поток stdout
является буферизуемым. Записываемые в него данные не посылаются на консоль (или на другое устройство в случае перенаправления), пока буфер не заполнится, программа не завершит работу нормальным способом или файл stdout
не будет закрыт. Осуществить принудительное "выталкивание" буфера позволяет функция fflush()
:
fflush(stdout);
В то же время поток stderr
не буферизуется. Записываемые в него данные сразу попадают на консоль.[6]
Указанная особенность потока stdout
может приводить к неожиданным результатам. Например, в следующем цикле точка не выводится каждую секунду. Вместо этого все символы сначала помещаются в буфер, а затем целая их группа одновременно выводится на экран, когда буфер оказывается заполненным.
while (1) {
printf(".");
sleep(1);
}
А в этом цикле происходит то, что нам нужно:
while (1) {
fprintf(stderr, ".");
sleep(1);
}
- 14.1.4. Стандартный ввод и вывод
- 4.4. Ввод и вывод
- Глава 7. Ввод и вывод
- Перенаправление ввода
- Вывод на экран текстовых строк
- 14.1.2. Перехват вывода программы
- ГЛАВА 5 ВВОД И ВЫВОД
- 7.1 Стандартный ввод-вывод
- Пример: функция str_echo, использующая стандартный ввод-вывод
- 14.8. Сокеты и стандартный ввод-вывод
- Стандартные потоки: stdin, stdout, stdeir, stdaux, stdprn.
- 9.5. Пример: двусторонние каналы в gawk