Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

9.3.1.1. Создание каналов

Системный вызов

pipe
создает канал:

#include <unistd.h> /* POSIX */

int pipe(int filedes[2]);

Значение аргумента является адресом массива из двух элементов целого типа,

pipe
возвращает 0 при успешном возвращении и -1, если была ошибка.

Если вызов был успешным, у процесса теперь есть два дополнительных открытых дескриптора файла. Значение

filedes[0]
является читаемым концом канала, a
filedes [1]
 — записываемым концом. (Удобным мнемоническим способом запоминания является то, что читаемый конец использует индекс 0, аналогичный дескриптору стандартного ввода 0, а записываемый конец использует индекс 1, аналогичный дескриптору стандартного вывода 1.)

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

close
. Следующая простая программа,
ch09-pipedemo.c
, демонстрирует каналы путем создания канала, записи в него данных, а затем чтения этих данных из него:

1 /* ch09-pipedemo.c --- демонстрация ввода/вывода с каналом. */

2

3 #include <stdio.h>

4 #include <errno.h>

5 #include <unistd.h>

6

7 /* main --- создание канала, запись в него и чтение из него. */

8

9 int main(int argc, char **argv)

10 {

11 static const char mesg[] = "Don't Panic!"; /* известное сообщение */

12 char buf[BUFSIZ];

13 ssize_t rcount, wcount;

14 int pipefd[2];

15 size_t l;

16

17 if (pipe(pipefd) < 0) {

18 fprintf(stderr, "%s: pipe failed: %s\n", argv[0],

19 strerror(errno));

20 exit(1);

21 }

22

23 printf("Read end = fd %d, write end = fd %d\n",

24 pipefd[0], pipefd[1]);

25

26 l = strlen(mesg);

27 if ((wcount = write(pipefd[1], mesg, 1)) != 1) {

28 fprintf(stderr, "%s: write failed: %s\n", argv[0],

29 strerror(errno));

30 exit(1);

31 }

32

33 if ((rcount = read(pipefd[0], buf, BUFSIZ)) != wcount) {

34 fprintf(stderr, "%s: read failed: %s\n", argv[0],

35 strerror(errno));

36 exit(1);

37 }

38

39 buf[rcount] = '\0';

40

41 printf("Read <%s> from pipe\n", buf);

42 (void)close(pipefd[0]);

43 (void)close(pipefd[1]);

44

45 return 0;

46 }

Строки 11–15 объявляют локальные переменные; наибольший интерес представляет

mesg
, который представляет текст, проходящий по каналу.

Строки 17–21 создают канал с проверкой ошибок; строки 23–24 выводят значения новых дескрипторов файлов (просто для подтверждения, что они не равны 0, 1 или 2)

В строке 26 получают длину сообщения для использования с

write
. Строки 27–31 записывают сообщение в канал, снова с проверкой ошибок.

Строки 33–37 считывают содержимое канала, опять с проверкой ошибок. Строка 39 предоставляет завершающий нулевой байт, так что прочитанные данные могут использоваться в качестве обычной строки. Строка 41 выводит данные, а строки 42–43 закрывают оба конца канала. Вот что происходит при запуске программы:

$ ch09-pipedemo

Read end = fd 3, write end = fd 4

Read <Don't Panic!> from pipe

Эта программа не делает ничего полезного, но она демонстрирует основы. Обратите внимание, что нет вызовов

open
или
creat
и что программа не использует три своих унаследованных дескриптора. Тем не менее,
write
и
read
завершаются успешно, показывая, что дескрипторы файлов действительны и что данные, поступающие в канал, действительно выходят из него. [95] Конечно, будь сообщение слишком большим, наша программа не работала бы. Это происходит из-за того, что размер (памяти) каналов ограничен, факт, который мы обсудим в следующем разделе.

95

Мы уверены, что вы не волновались. В конце концов, вы, возможно, используете конвейеры из оболочки десятки раз в день — Примеч. автора.

Подобно другим дескрипторам файлов, дескрипторы для каналов наследуются порожденным процессом после

fork
, и если они не закрываются, все еще доступны после
exec
. Вскоре мы увидим, как использовать это обстоятельство и сделать с каналами что-то интересное.

9.3.1.2. Буферирование каналов

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

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

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

Подобным же образом, если канал пустой, потребитель блокируется в

read
до тех пор, пока в канале не появятся данные для чтения. (Блокирующее поведение можно отключить; это обсуждается в разделе 9.4.3.4 «Неблокирующий ввод/вывод для каналов и очередей FIFO».)

Поделиться:
Популярные книги

Матабар

Клеванский Кирилл Сергеевич
1. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар

Русская драматургия XVIII – XIX вв. (Сборник)

Пушкин Александр Сергеевич
Поэзия:
драматургия
6.25
рейтинг книги
Русская драматургия XVIII – XIX вв. (Сборник)

Тринадцатый X

NikL
10. Видящий смерть
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Тринадцатый X

Прайм. Хомори

Бор Жорж
2. Легенда
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Прайм. Хомори

Девять драконов

Скотт Джастин
Детективы:
триллеры
5.00
рейтинг книги
Девять драконов

Стражи душ

Кас Маркус
4. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Стражи душ

Двойник короля 20

Скабер Артемий
20. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 20

Точка Бифуркации IV

Смит Дейлор
4. ТБ
Фантастика:
героическая фантастика
городское фэнтези
попаданцы
5.00
рейтинг книги
Точка Бифуркации IV

Юнлинг

Метельский Николай Александрович
Фантастика:
героическая фантастика
космическая фантастика
попаданцы
8.35
рейтинг книги
Юнлинг

Двойник короля 14

Скабер Артемий
14. Двойник Короля
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Двойник короля 14

Убивать чтобы жить 4

Бор Жорж
4. УЧЖ
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 4

Старый, но крепкий 4

Крынов Макс
4. Культивация без насилия
Фантастика:
уся
фэнтези
5.00
рейтинг книги
Старый, но крепкий 4

Неучтенный элемент. Том 8

NikL
8. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 8

Бастард Императора. Том 9

Орлов Андрей Юрьевич
9. Бастард Императора
Фантастика:
городское фэнтези
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Бастард Императора. Том 9