Назначение переменных, описанных в программе:
command
Код управляющего действия.
choice
Используется для выбора поля ассоциированной структуры данных, которое нужно изменить.
msqid_ds
Структура для хранения информации об очереди.
Затем нужно ввести код выбранного управляющего действия (строки 17-22); он заносится в переменную command.
Если выбрано действие IPC_STAT (код 1), системный вызов выполняется (строка 31) и распечатывается информация о состоянии очереди (строки 32-39); в программе распечатываются только те поля структуры, которые могут быть переустановлены. Отметим, что если системный вызов завершается неудачей, распечатывается информация о состоянии очереди на момент последнего успешного выполнения системного вызова. Кроме того, выводится сообщение об ошибке и распечатывается значение переменной errno (строки 90, 91). Если системный вызов завершается успешно, выводится сообщение, уведомляющее об этом, и значение использованного идентификатора очереди сообщений (строки 95, 96).
Если выбрано действие IPC_SET (код 2), программа прежде всего получает информацию о текущем состоянии очереди сообщений с заданным идентификатором (строка 45). Это необходимо, поскольку пример обеспечивает изменение только одного поля за один раз, в то время как системный вызов изменяет всю структуру целиком. Кроме того, если в одно из полей структуры, находящейся в об- ласти памяти пользователя, будет занесено некорректное значение, это может вызвать неудачи в выполнении управляющих действий, повторяющиеся до тех пор, пока значение поля не будет исправлено. Затем программа предлагает ввести код, соответствующий полю структуры, которое должно быть изменено (строки 46-53). Этот код заносится в переменную choice. Далее, в зависимости от указанного поля, программа предлагает ввести то или иное новое значение (строки 54-79). Значение заносится в соответствующее поле структуры данных, расположенной в области памяти пользователя, и выполняется системный вызов (строка 81).
Если выбрано действие IPC_RMID (код 3), выполняется системный вызов (строка
86), удаляющий из системы идентификатор msqid, очередь сообщений и
ассоциированную с ней структуру данных. Отметим, что для выполнения этого
управляющего действия аргумент buf не требуется, поэтому его значение может
быть заменено нулем (NULL).
1 /* Программа иллюстрирует
2 возможности системного вызова msgctl()
3 (управление очередями сообщений) */
4 #include <stdio.h>
5 #include <sys/types.h>
6 #include <sys/ipc.h>
7 #include <sys/msg.h>
8 main ()
9 {
10 extern int errno;
11 int msqid, command, choice, rtrn;
12 struct msqid_ds msqid_ds, *buf;
13 buf = &msqid_ds;
14 /* Ввести идентификатор и действие */
15 printf ("Введите идентификатор msqid: ");
16 scanf ("%d", &msqid);
17 printf ("Введите номер требуемого действия:\n");
18 printf (" IPC_STAT = 1\n");
19 printf (" IPC_SET = 2\n");
20 printf (" IPC_RMID = 3\n");
21 printf (" Выбор = ");
22 scanf ("%d", &command);
23 /* Проверить значения */
24 printf ("идентификатор = %d, действие = %d\n",
25 msqid, command);
26 switch (command) {
27 case 1: /* Скопировать информацию
28 о состоянии очереди сообщений
29 в пользовательскую структуру
30 и вывести ее */
31 rtrn = msgctl (msqid, IPC_STAT, buf);
32 printf ("\n Идентификатор пользователя = %d\n",
33 buf->msg_perm.uid);
34 printf ("\n Идентификатор группы = %d\n",
35 buf->msg_perm.gid);
36 printf ("\n Права на операции = 0%o\n",
37 buf->msg_perm.mode);
38 printf ("\n Размер очереди в байтах = %d\n",
39 buf->msg_qbytes);
40 break;
41 case 2: /* Выбрать и изменить поле (поля)
42 ассоциированной структуры данных */
43 /* Сначала получить исходное значение
44 структуры данных */
45 rtrn = msgctl (msqid, IPC_STAT, buf);
46 printf ("\nВведите номер поля, ");
47 printf ("которое нужно изменить:\n");
48 printf (" msg_perm.uid = 1\n");
49 printf (" msg_perm.gid = 2\n");
50 printf (" msg_perm.mode = 3\n");
51 printf (" msg_qbytes = 4\n");
52 printf (" Выбор = ");
53 scanf ("%d", &choice);
54 switch (choice) {
55 case 1:
56 printf ("\nВведите ид-р пользователя: ");
57 scanf ("%d", &buf->msg_perm.uid);
58 printf ("\nИд-р пользователя = %d\n",
59 buf->msg_perm.uid);
60 break;
61 case 2:
62 printf ("\nВведите ид-р группы: ");
63 scanf ("%d", &buf->msg_perm.gid);
64 printf ("\nИд-р группы = %d\n",
65 buf->msg_perm.uid);
66 break;
67 case 3:
68 printf ("\nВведите восьмеричный код прав: ");
69 scanf ("%o", &buf->msg_perm.mode);
70 printf ("\nПрава на операции = 0%o\n",
71 buf->msg_perm.mode);
72 break;
73 case 4:
74 printf ("\nВведите размер очереди = ");
75 scanf ("%d", &buf->msg_qbytes);
76 printf ("\nЧисло байт в очереди = %d\n",
77 buf->msg_qbytes);
78 break;
79 }
80 /* Внести изменения */
81 rtrn = msgctl (msqid, IPC_SET, buf);
82 break;
83 case 3: /* Удалить идентификатор и
84 ассоциированные с ним очередь
85 сообщений и структуру данных */
86 rtrn = msgctl (msqid, IPC_RMID, NULL);
87 }
88 if (rtrn == -1) {
89 /* Сообщить о неудачном завершении */
90 printf ("\nmsgctl завершился неудачей!\n");
91 printf ("\nКод ошибки = %d\n", errno);
92 }
93 else {
94 /* При успешном завершении сообщить msqid */
95 printf ("\nmsgctl завершился успешно,\n");
96 printf ("идентификатор = %d\n", msqid);
97 }
98 exit (0);
99 }