Уильям Стивенс - UNIX: взаимодействие процессов

Тут можно читать онлайн Уильям Стивенс - UNIX: взаимодействие процессов - бесплатно ознакомительный отрывок. Жанр: comp-programming, издательство Питер, год 2003. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX: взаимодействие процессов
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2003
  • Город:
    Санкт-Петербург
  • ISBN:
    5-318-00534-9
  • Рейтинг:
    3.6/5. Голосов: 101
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Уильям Стивенс - UNIX: взаимодействие процессов краткое содержание

UNIX: взаимодействие процессов - описание и краткое содержание, автор Уильям Стивенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

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

UNIX: взаимодействие процессов - читать онлайн бесплатно ознакомительный отрывок

UNIX: взаимодействие процессов - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Уильям Стивенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

7 struct mymesg {

8 long mesg_len; //количество байтов в mesg_data, может быть О

9 long mesg_type;//тип сообщения, должен быть > 0

10 char mesg_data[MAXMESGDATA];

11 };

12 ssize_t mesg_send(int, struct mymesg *);

13 void Mesg_send(int, struct mymesg *);

14 ssize_t mesg_recv(int, struct mymesg *);

15 ssize_t Mesg_recv(int, struct mymesg *);

Каждое сообщение содержит в себе информацию о своем типе (mesg_type), причем значение этой переменной должно быть больше нуля. Пока мы будем игнорировать это поле в записи, но вернемся к нему в главе 6, где описываются очереди сообщений System V. Каждое сообщение также обладает длиной, кoтopая может быть и нулевой. Структура mymesg позволяет предварить каждое сообщение информацией о его типе и длине вместо использования символа перевода строки для сигнализации конца сообщения. Ранее мы отметили два преимущества этого подхода: получатель не должен сканировать все принятые байты в поисках конца сообщения и отсутствует необходимость исключать появление разделителя в самих данных.

На рис. 4.13 изображен вид структуры mymesg и ее использование с каналами, FIFO и очередями сообщений System V.

Рис. 4.13. Структура mymesg

Мы определяем две функции для отправки и приема сообщений. В листинге 4.13 приведен текст функции mesg_send, а в листинге 4.14 — функции mesg_recv.

Листинг 4.13. Функция mesg_send

//pipemesg/mesg_send.c

1 #include "mesg.h"

2 ssize_t

3 mesg_send(int fd, struct mymesg *mptr)

4 {

5 return(write(fd, mptr, MESGHDRSIZE + mptr->mesg_len));

6 }

Листинг 4.14. Функция mesg_recv

//pipemesg/mesg_recv.c

1 #include "mesg.h"

2 ssize_t

3 mesg_recv(int fd, struct mymesg *mptr)

4 {

5 size_t len;

6 ssize_t n;

8 /* считывание заголовка сообщения для определения его длины */

9 if ((n = Read(fd, mptr, MESGHDRSIZE)) == 0)

10 return(0); /* end of file */

11 else if (n != MESGHDRSIZE)

12 err_quit("message header: expected %d, got %d". MESGHDRSIZE, n);

13 if ((len = mptr->mesg_len) > 0)

14 if ((n = Read(fd, mptr->mesg_data, len)) != len)

15 err_quit("message data: expected %d, got %d", len, n);

16 return(len);

17 }

Теперь для каждого сообщения функция read вызывается дважды: один раз для считывания длины, а другой — для считывания самого сообщения (если его длина больше 0).

ПРИМЕЧАНИЕ

Внимательные читатели могли заметить, что функция mesg_recv проверяет наличие всех возможных ошибок и прекращает работу при их обнаружении. Однако мы все же определили функцию-обертку Mesg_recv и вызываем из наших программ именно ее — для единообразия.

Изменим теперь функции client и server, чтобы воспользоваться новыми функциями mesg_send и mesg_recv. В листинге 4.15 приведен текст функции-клиента.

Листинг 4.15. Функция client с использованием сообщений

//pipemesg/client.c

1 #include "mesg.h"

2 void

3 client(int readfd, int writefd)

4 {

5 size_t len;

6 ssize_t n;

7 struct mymesg mesg;

8 /* считывание полного имени */

9 Fgets(mesg.mesg_data, MAXMESGDATA, stdin);

10 len = strlen(mesg.mesg_data);

11 if (mesg.mesg_data[len-1] == '\n')

12 len--; /* удаление перевода строки из fgets() */

13 mesg.mesg_len = len;

14 mesg.mesg_type = 1;

15 /* запись полного имени в канал IPC */

16 Mesg_send(writefd, &mesg);

17 /* считывание из канала IPC. запись в stdout */

18 while ( (n = Mesg_recv(readfd, &mesg)) > 0)

19 Write(STDOUT_FILENO, mesg.mesg_data, n);

20 }

Считывание имени файла и отправка его серверу

8-16 Полное имя считывается из стандартного потока ввода и затем отправляется на сервер с помощью функции mesg_send.

Считывание содержимого файла или сообщения об ошибке от сервера

17-19 Клиент вызывает функцию mesg_recv в цикле, считывая все приходящие от сервера сообщения. По соглашению, когда mesg_recv возвращает нулевую длину сообщения, это означает конец передаваемых сервером данных. Мы увидим, что сервер добавляет символ перевода строки к каждому сообщению, отправляемому клиенту, поэтому пустая строка будет иметь длину сообщения 1. В листинге 4.16 приведен текст функции-сервера.

Листинг 4.16. Функция server, использующая сообщения

//pipemesg/server.c

1 #include "mesg.h"

2 void

3 server(int readfd, int writefd)

4 {

5 FILE *fp;

6 ssize_t n;

7 struct mymesg mesg;

8 /* считывание полного имени из канала */

9 mesg.mesg_type = 1;

10 if ((n = Mesg_recv(readfd, &mesg)) == 0)

11 err_quit("pathname missing");

12 mesg.mesg_data[n] = '\0'; /* полное имя, завершающееся 0 */

13 if ((fp = fopen(mesg.mesg_data, "r")) == NULL) {

14 /* ошибка, нужно сообщить клиенту */

15 snprintf(mesg.mesg_data + n, sizeof(mesg.mesg_data) – n,

16 ": can't open, %s\n", strerror(errno));

17 mesg.mesg_len = strlen(mesg.mesg_data);

18 Mesg_send(writefd, &mesg);

19 } else {

20 /* файл успешно открыт, передача данных */

21 while (Fgets(mesg.mesg_data, MAXMESGDATA, fp) != NULL) {

22 mesg.mesg_len = strlen(mesg.mesg_data);

23 Mesg_send(writefd, &mesg);

24 }

25 Fclose(fp);

26 }

27 /* отправка сообщения нулевой длины для обозначения конца связи */

28 mesg.mesg_len = 0;

29 Mesg_send(writefd, &mesg);

30 }

Считывание имени файла из канала IPC, открытие файла

8-18 Сервер принимает от клиента имя файла. Хотя значение mesg_type, равное 1, нигде не используется (оно затирается функцией mesg_recv из листинга 4.14), мы будем использовать ту же функцию при работе с очередями сообщений System V (листинг 6.8), а в данном случае в этом значении уже возникает потребность (см., например, листинг 6.11). Стандартная функция ввода-вывода fopen открывает файл, что отличается от листинга 4.3, где вызывалась функция open для получения дескриптора файла. Причина, по которой мы воспользовались fopen, заключается в том, что в этой пpoгрaммe мы пользуемся библиотечной функцией fgets для считывания содержимого файла построчно и затем отправляем клиенту строку за строкой.

Отправка файла клиенту

19-26 Если вызов fopen оказывается успешным, содержимое файла считывается с помощью функции fgets и затем отправляется клиенту построчно. Сообщение с нулевой длиной означает конец файла.

При использовании пpoгрaммныx каналов или FIFO мы могли бы также закрыть канал IPC, чтобы дать клиенту знать о том, что передача файла завершена. Однако мы используем передачу сообщения нулевой длины, потому что другие типы IPC не поддерживают концепцию конца файла.

Функции main, вызывающие новые функции client и server, вообще не претерпели никаких изменений. Мы можем использовать либо версию для работы с каналами (листинг 4.1), либо версию для работы с FIFO (листинг 4.6).

4.11. Ограничения программных каналов и FIFO

На программные каналы и каналы FIFO системой накладываются всего два ограничения:

■ OPEN_MAX — максимальное количество дескрипторов, которые могут быть одновременно открыты некоторым процессом (Posix устанавливает для этой величины ограничение снизу — 16);

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




UNIX: взаимодействие процессов отзывы


Отзывы читателей о книге UNIX: взаимодействие процессов, автор: Уильям Стивенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x