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

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

Жанры

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».)

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

Идеальный мир для Лекаря 10

Сапфир Олег
10. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 10

На границе империй. Том 10. Часть 8

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 8

Газлайтер. Том 27

Володин Григорий Григорьевич
27. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 27

Виконт. Книга 2. Обретение силы

Юллем Евгений
2. Псевдоним `Испанец`
Фантастика:
боевая фантастика
попаданцы
рпг
7.10
рейтинг книги
Виконт. Книга 2. Обретение силы

Первый среди равных. Книга VII

Бор Жорж
7. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Первый среди равных. Книга VII

Гримуар темного лорда IV

Грехов Тимофей
4. Гримуар темного лорда
Фантастика:
фэнтези
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Гримуар темного лорда IV

Приказано выжить!

Малыгин Владимир
1. Другая Русь
Фантастика:
боевая фантастика
попаданцы
альтернативная история
7.09
рейтинг книги
Приказано выжить!

Дважды одаренный. Том IV

Тарс Элиан
4. Дважды одаренный
Фантастика:
городское фэнтези
альтернативная история
аниме
7.00
рейтинг книги
Дважды одаренный. Том IV

Дворянская кровь

Седой Василий
1. Дворянская кровь
Фантастика:
попаданцы
альтернативная история
7.00
рейтинг книги
Дворянская кровь

Вперед в прошлое 9

Ратманов Денис
9. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 9

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

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

Законы рода

Андрей Мельник
1. Граф Берестьев
Фантастика:
фэнтези
боевая фантастика
аниме
5.00
рейтинг книги
Законы рода

Черный Маг Императора 4

Герда Александр
4. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 4

Кодекс Охотника XXXI

Винокуров Юрий
31. Кодекс Охотника
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Охотника XXXI