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

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

Жанры

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

Стивенс Уильям Ричард

Шрифт:

35 /* ожидаем помещения сообщения в очередь */

36 mqhdr->mqh_nwait++;

37 while (attr->mq_curmsgs == 0)

38 pthread_cond_wait(&mqhdr->mqh_wait, &mqhdr->mqh_lock);

39 mqhdr->mqh_nwait--;

40 }

Листинг 5.28. Функция mq_receive: вторая половина

//my_pxmsg_mmap/mq_receive.c

41
if ((index = mqhdr->mqh_head) == 0)

42 err_dump("mymq_receive: curmsgs = %ld; head = 0", attr->mq_curmsgs);

43 msghdr = (struct mymsg_hdr *) &mptr[index];

44 mqhdr->mqh_head = msghdr->msg_next; /* новое начало списка */

45 len = msghdr->msg_len;

46 memcpy(ptr, msghdr + 1, len); /* копирование самого сообщения */

47 if (priop != NULL)

48 *priop = msghdr->msg_prio;

49 /* только что считанное сообщение становится первым в списке пустых */

50 msghdr->msg_next = mqhdr->mqr_free;

51 mqhdr->mqh_free = index;

52 /* запуск любого процесса, заблокированного в вызове mq_send */

53 if (attr->mq_curmsgs == attr->mq_maxmsg)

54 pthread_cond_signal(&mqhdr->mqh_wait);

55 attr->mq_curmsgs--;

56 pthread_mutex_unlock(&mqhdr->mqh_lock);

57 return(len);

58 err:

59 pthread_mutex_unlock(&mqhdr->mqh_lock);

60 return(-1);

61 }

Возвращение сообщения вызвавшему процессу

43-51 msghdr указывает на msg_hdr первого сообщения в очереди, которое мы и возвратим. Освободившееся сообщение становится первым в списке свободных. 

Разблокирование процесса, заблокированного в вызове mq_send

52-54 Если очередь была полной в момент считывания сообщения, мы вызываем pthread_cond_signal для отправки сообщения любому из процессов, заблокированных в вызове mq_send.

5.9. Резюме

Очереди сообщений Posix просты в использовании: новая очередь создается (или существующая открывается) функцией mq_open; закрываются очереди вызовом mq_close, а удаляются mq_unlink. Поместить сообщение в очередь можно функцией mq_send, а считать его оттуда можно с помощью mq_receive. Атрибуты очереди можно считать и установить с помощью функций mq_getattr и mq_setattr, а функция mq_notify позволяет зарегистрировать процесс на уведомление о помещении нового сообщения в пустую очередь. Каждое сообщение в очереди обладает приоритетом (небольшое целое число), и функция mq_receive всегда возвращает старейшее сообщение с наивысшим приоритетом.

Изучая mq_notify, мы познакомились с сигналами реального времени стандарта Posix, которые обладают номерами от SIGMIN до SIGMAX. При установке обработчика для этих сигналов с флагом SA_SIGINFO они будут помещаться в очередь, доставляться в порядке очереди и сопровождаться двумя дополнительными аргументами (при вызове обработчика).

Наконец, мы реализовали большую часть возможностей очереди сообщений Posix в приблизительно 500 строках кода на языке С, используя отображаемые в память файлы, взаимные исключения и условные переменные Posix. Эта реализация иллюстрирует обработку ситуации гонок при создании новой очереди; еще раз нам придется столкнуться с такой ситуацией в главе 10 при реализации семафоров Posix.

Упражнения

1. Говоря о листинге 5.4, мы отметили, что атрибут attr функции mq_open при создании новой очереди является ненулевым; следует указать оба поля: mq_maxmsg и mq_msgsize. Как можно было бы указать только одно из них, не указывая второе, для которого использовать значения атрибутов по умолчанию?

2. Измените листинг 5.8 так, чтобы при получении сигнала не вызывалась функция mq_notify. Затем поместите в очередь два сообщения и убедитесь, что для второго из них сигнал порожден не будет. Почему?

3. Измените листинг 5.8 так, чтобы сообщение из очереди при получении сигнала не считывалось. Вместо этого просто вызовите mq_notify и напечатайте сообщение о получении сигнала. Затем отправьте два сообщения и убедитесь, что для второго из них сигнал не порождается. Почему?

4. Что произойдет, если мы уберем преобразование двух констант к целому типу в первом вызове printf в листинге 5.14? 

5. Измените листинг 5.4 следующим образом: перед вызовом mq_open напечатайте сообщение и подождите 30 секунд (sleep). После возвращения из mq_open выведите еще одно сообщение и подождите еще 30 секунд, а затем вызовите mq_close. Откомпилируйте программу и запустите ее, указав большое количество сообщений (несколько сотен тысяч) и максимальный размер сообщения, скажем, в 10 байт. Задача заключается в том, чтобы создать большую очередь и проверить, используются ли в реализации отображаемые в память файлы. В течение 30-секундной паузы запустите программу типа ps и посмотрите на занимаемый программой объем памяти. Сделайте это еще раз после возвращения из mq_open. Можете ли вы объяснить происходящее?

6. Что произойдет при вызове memcpy в листинге 5.26, если вызвавший процесс укажет нулевую длину сообщения?

7. Сравните очередь сообщений с двусторонними каналами, описанными в разделе 4.4. Сколько очередей нужно для двусторонней связи между родительским и дочерним процессами?

8. Почему мы не удаляем взаимное исключение и условную переменную в листинге 5.20?

9. Стандарт Posix утверждает, что дескриптор очереди сообщений не может иметь тип массива. Почему? 

10. В каком состоянии проводит большую часть времени функция main из листинга 5.12? Что происходит каждый раз при получении сигнала? Как мы обрабатываем эту ситуацию?

11. Не все реализации поддерживают атрибут PTHREAD_PROCESS_SHARED для взаимных исключений и условных переменных. Переделайте реализацию очередей сообщений из раздела 5.8 так, чтобы использовать семафоры Posix (глава 10) вместо взаимных исключений и условных переменных.

12. Расширьте реализацию очередей сообщений Posix из раздела 5.8 так, чтобы она поддерживала SIGEV_THREAD. 

ГЛАВА 6

Очереди сообщений System V

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

Я Гордый часть 7

Машуков Тимур
7. Стальные яйца
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Я Гордый часть 7

Кукловод

Злобин Михаил
2. О чем молчат могилы
Фантастика:
боевая фантастика
8.50
рейтинг книги
Кукловод

Наемный корпус

Вайс Александр
5. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Наемный корпус

Иной. Том 1. Школа на краю пустыни

Amazerak
1. Иной в голове
Фантастика:
боевая фантастика
рпг
аниме
5.75
рейтинг книги
Иной. Том 1. Школа на краю пустыни

Подпольная империя

Ромов Дмитрий
4. Цеховик
Фантастика:
попаданцы
альтернативная история
6.60
рейтинг книги
Подпольная империя

Воплощение Похоти

Некрасов Игорь
1. Воплощение Похоти
Фантастика:
юмористическое фэнтези
попаданцы
рпг
аниме
5.00
рейтинг книги
Воплощение Похоти

Семьи.net (сборник)

Панов Вадим Юрьевич
Фантастика:
социально-философская фантастика
научная фантастика
4.40
рейтинг книги
Семьи.net (сборник)

Последний Паладин. Том 12

Саваровский Роман
12. Путь Паладина
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 12

Хозяин Теней 4

Петров Максим Николаевич
4. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Хозяин Теней 4

Бастард Императора

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

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

Телохранитель Генсека. Том 2

Алмазный Петр
2. Медведев
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Телохранитель Генсека. Том 2

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

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

Я – Легенда 2: геном хищника

Гарцевич Евгений Александрович
2. Я - Легенда!
Фантастика:
боевая фантастика
рпг
фантастика: прочее
попаданцы
5.00
рейтинг книги
Я – Легенда 2: геном хищника