next up previous contents index
Next: Операции над очередями сообщений Up: Управление очередями сообщений Previous: Использование msgctl   Contents   Index

Программа-пример

Назначение переменных, описанных в программе:

command

Код управляющего действия.

choice

Используется для выбора поля ассоциированной структуры данных, которое нужно изменить.

msqid_ds

Структура для хранения информации об очереди.

Программа ведет себя следующим образом. Прежде всего предлагается ввести допустимый идентификатор очереди сообщений, который заносится в переменную msqid (строки 15, 16). Это значение требуется в каждом системном вызове msgctl.

Затем нужно ввести код выбранного управляющего действия (строки 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 }



Alex Otwagin 2002-12-16