В справочной статье msgctl синтаксис данного системного вызова описан так:
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl ( int msqid, int cmd, struct msqid_ds *buf);
В качестве аргумента msqid должен выступать идентификатор очереди сообщений, предварительно полученный при помощи системного вызова msgget.
Управляющее действие определяется значением аргумента cmd. Допустимых значений три:
Поместить информацию о состоянии очереди, содержащуюся в структуре данных, ассоциированной с идентификатором msqid, в пользовательскую структуру, на которую указывает аргумент buf.
В структуре данных, ассоциированной с идентификатором msqid, переустановить значения действующих идентификаторов пользователя и группы, прав на операции, максимально допустимого числа байт в очереди.
Удалить из системы идентификатор msqid, ликвидировать очередь сообщений и ассоциированную с ней структуру данных.
Ниже приведена программа-пример (рис. 18), иллюстрирующая управление очередью. В программе использованы следующие переменные:
Если выбрано действие IPC_STAT (код 1), выполняется системный вызов и распечатывается информация о состоянии очереди; в программе распечатываются только те поля структуры, которые могут быть переустановлены. Если системный вызов завершается неудачей, распечатывается информация о состоянии очереди на момент последнего успешного выполнения системного вызова. Кроме того, выводится сообщение об ошибке и распечатывается значение переменной errno. Если системный вызов завершается успешно, выводится сообщение, уведомляющее об этом, и значение использованного идентификатора очереди сообщений.
Если выбрано действие IPC_SET (код 2), программа прежде всего получает информацию о текущем состоянии очереди сообщений с заданным идентификатором. Это необходимо, поскольку пример обеспечивает изменение только одного поля за один раз, в то время как системный вызов изменяет всю структуру целиком. Кроме того, если в одно из полей структуры, находящейся в области памяти пользователя, будет занесено некорректное значение, это может вызвать неудачи в выполнении управляющих действий, повторяющиеся до тех пор, пока значение поля не будет исправлено. Затем программа предлагает ввести код, соответствующий полю структуры, которое должно быть изменено. Этот код заносится в переменную choice. Далее, в зависимости от указанного поля, программа предлагает ввести то или иное новое значение. Значение заносится в соответствующее поле структуры данных, расположенной в области памяти пользователя, и выполняется системный вызов.
Если выбрано действие IPC_RMID (код 3), выполняется системный вызов, удаляющий из системы идентификатор msqid, очередь сообщений и ассоциированную с ней структуру данных. Отметим, что для выполнения этого управляющего действия аргумент buf не требуется, поэтому его значение может быть заменено нулем (NULL).
возможности системного вызова msgctl()
(управление очередями сообщений) */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
main ()
{
extern int errno;
int msqid, command, choice, rtrn;
struct msqid_ds msqid_ds, *buf;
buf = &msqid_ds;
/* Ввести идентификатор и действие */
printf ("Введите идентификатор msqid: ");
scanf ("%d", &msqid);
printf ("Введите номер требуемого действия:\n");
printf (" IPC_STAT = 1\n");
printf (" IPC_SET = 2\n");
printf (" IPC_RMID = 3\n");
printf (" Выбор = ");
scanf ("%d", &command);
/* Проверить значения */
printf ("идентификатор = %d, действие = %d\n",
msqid, command);
switch (command) {
case 1: /* Скопировать информацию
о состоянии очереди сообщений
в пользовательскую структуру
и вывести ее */
rtrn = msgctl (msqid, IPC_STAT, buf);
printf ("\n Идентификатор пользователя = %d\n",
buf->msg_perm.uid);
printf ("\n Идентификатор группы = %d\n",
buf->msg_perm.gid);
printf ("\n Права на операции = 0%o\n",
buf->msg_perm.mode);
printf ("\n Размер очереди в байтах = %d\n",
buf->msg_qbytes);
break;
case 2: /* Выбрать и изменить поле (поля)
ассоциированной структуры данных */
/* Сначала получить исходное значение
структуры данных */
rtrn = msgctl (msqid, IPC_STAT, buf);
printf ("\nВведите номер поля, ");
printf ("которое нужно изменить:\n");
printf (" msg_perm.uid = 1\n");
printf (" msg_perm.gid = 2\n");
printf (" msg_perm.mode = 3\n");
printf (" msg_qbytes = 4\n");
printf (" Выбор = ");
scanf ("%d", &choice);
switch (choice) {
case 1:
printf ("\nВведите ид-р пользователя: ");
scanf ("%d", &buf->msg_perm.uid);
printf ("\nИд-р пользователя = %d\n",
buf->msg_perm.uid);
break;
case 2:
printf ("\nВведите ид-р группы: ");
scanf ("%d", &buf->msg_perm.gid);
printf ("\nИд-р группы = %d\n",
buf->msg_perm.uid);
break;
case 3:
printf ("\nВведите восьмеричный код прав: ");
scanf ("%o", &buf->msg_perm.mode);
printf ("\nПрава на операции = 0%o\n",
buf->msg_perm.mode);
break;
case 4:
printf ("\nВведите размер очереди = ");
scanf ("%d", &buf->msg_qbytes);
printf ("\nЧисло байт в очереди = %d\n",
buf->msg_qbytes);
break;
}
/* Внести изменения */
rtrn = msgctl (msqid, IPC_SET, buf);
break;
case 3: /* Удалить идентификатор и
ассоциированные с ним очередь
сообщений и структуру данных */
rtrn = msgctl (msqid, IPC_RMID, NULL);
}
if (rtrn == -1) {
/* Сообщить о неудачном завершении */
printf ("\nmsgctl завершился неудачей!\n");
printf ("\nКод ошибки = %d\n", errno);
}
else {
/* При успешном завершении сообщить msqid */
printf ("\nmsgctl завершился успешно,\n");
printf ("идентификатор = %d\n", msqid);
}
exit (0);
}