19 msgsize = MSGSIZE(attr->mq_msgsize);
20 filesize = sizeof(struct mymq_hdr) + (attr->mq_maxmsg *
21 (sizeof(struct mymsg_hdr) + msgsize));
22 if (munmap(mqinfo->mqi_hdr, filesize) == –1)
23 return(-1);
24 mqinfo->mqi_magic = 0; /* на всякий случай */
25 free(mqinfo);
26 return(0);
27 }
10-16 Проверяется правильность переданных аргументов, после чего получаются указатели на область, занятую отображенным в память файлом (mqhdr), и атрибуты (в структуре mq_hdr).
17-18 Для сброса регистрации на уведомление вызвавшего процесса мы вызываем mq_notify. Если процесс был зарегистрирован, он будет снят с уведомления, но если нет — ошибка не возвращается.
19-25 Мы вычисляем размер файла для вызова munmap и освобождаем память, используемую структурой mqinfo. На случай, если вызвавший процесс будет продолжать использовать дескриптор очереди сообщений, до того как область памяти будет вновь задействована вызовом malloc, мы устанавливаем значение mq_magiс в ноль, чтобы наши функции для работы с очередью сообщений обнаруживали ошибку.
Обратите внимание, что если процесс завершает работу без вызова mq_close, эти же операции выполняются автоматически: отключается отображение в память, а память освобождается.
Функция mq_unlink
Текст функции mqunlink приведен в листинге 5.21. Она удаляет файл, связанный с очередью сообщений, вызывая функцию unlink.
//my_pxmsg_mmap/mq_unlink.с
1 #include "unpipc.h"
2 #include "mqueue.h"
3 int
4 mymq_unlink(const char *pathname)
5 {
6 if (unlink(pathname) == –1)
7 return(-1);
8 return(0);
9 }
Функция mq_getattr
В листинге 5.22 приведен текст функции mq_getattr, которая возвращает текущее значение атрибутов очереди.
//my_pxmsg_mmap/mq_getattr.с
1 #include "unpipc.h"
2 #include "mqueue.h"
3 int
4 mymq_getattr(mymqd_t mqd, struct mymq_attr *mqstat)
5 {
6 int n;
7 struct mymq_hdr *mqhdr;
8 struct mymq_attr *attr;
9 struct mymq_info *mqinfo;
10 mqinfo = mqd;
11 if (mqinfo->mqi_magic != MQI_MAGIC) {
12 errno = EBADF;
13 return(-1);
14 }
15 mqhdr = mqinfo->mqi_hdr;
16 attr = &mqhdr->mqh_attr;
17 if ((n = pthread_mutex_lock(&mqhdr->mqh_lock)) != 0) {
18 errno = n;
19 return (-1);
20 }
21 mqstat->mq_flags = mqinfo->mqi_flags; /* для каждого open */
22 mqstat->mq_maxmsg = attr->mq_maxmsg; /* оставшиеся три – для очереди */
23 mqstat->mq_msgsize = attr->mq_msgsize;
24 mqstat->mq_curmsgs = attr->mq_curmsgs;
25 pthread_mutex_unlock(&mqhdr->mqh_lock);
26 return(0);
27 }
17-20 Мы должны заблокировать соответствующее взаимное исключение для работы с очередью, в частности для получения атрибутов, поскольку какой-либо другой поток может в это время их изменить.
Функция mq_setattr
В листинге 5.23 приведен текст функции mq_setattr, которая устанавливает значение атрибутов очереди.
22-27 Если третий аргумент представляет собой ненулевой указатель, мы возвращаем предыдущее значение атрибутов перед внесением каких-либо изменений.
28-31 Единственный атрибут, который можно менять с помощью нашей функции, — mq_flags, хранящийся в структуре mq_infо.
//my_pxmsg_mniap/mq_setattr.с
1 #include "unpipc.h"
2 #include "mqueue.h"
3 int
4 mymq_setattr(mymqd_t mqd. const struct mymq_attr *mqstat,
5 struct mymq attr *omqstat)
6 {
7 int n;
8 struct mymq_hdr *mqhdr;