Руководство программиста для Linux


Очереди сообщений - часть 9


Эта функция-переходник возвращает 0, если очередь удалена без инцедентов, в противном случае ввыдается -1. Удаление очереди неделимо и попытка любого обращения к ней будет безуспешной.

msgtool: интерактивный обработчик очередей сообщений

Мало кто станет отрицать непосредственную выгоду от возможности в любой момент получить точную техническую информацию. Подобные материалы представляют собой мощный механизм для обучения и исследования новых областей. Однако, неплохо было бы добавить к технической информации и реальные примеры. Это непременно ускорит и укрепит процесс обучения.

До сей поры все то хорошее, что мы сделали - это оберточные функции для манипуляций с очередями сообщений. Хотя они чрезвычайно полезны, ими неудобно пользоваться для дальнейшего обучения и экспериментов. Существует средство, позволяющее работать с IPC-очередями из командной строки - msgtool(). Хотя msgtool() будет использован в целях обучения, он пригодится и реально при написании скриптов.

Описание

Поведение msgtool()-а зависит от аргументов командной строки, что удобно для вызова из скрипта shell. Позволяет делать все что угодно, от создания, посылки и получения сообщений до редактирования прав доступа и удаления очереди. Изначально данными сообщений могут быть только литерные массивы. Упражнение - измените это так, чтобы можно было посылать и другие данные. Синтаксис командной строки Посылка сообщений msgtool s (type) "text" Изъятие сообщений msgtool к (type) Изменение прав доступа msgtool (mode) Уничтожение очереди msgtool d Примеры msgtool s 1 test msgtool s 5 test msgtool s 1 "This is test" msgtool r 1 msgtool d msgtool m 660

Код

Следующее, что мы рассмотрим, это исходный текст msgtool. Его следует компилировать в версии системы, которая поддерживает System V IPC. Убедитесь в наличии System V IPC в ядре, когда будете пересобирать программу!

На полях отметим, что наша утилита будет всегда создавать очередь, если ее не было.

Замечание. Поскольку msgtool использует ftok() для генерации ключей IPC, вы можете нарваться на конфликты, связанные с директориями. Если вы где-то в скрипте меняете директории, то все это наверняка не сработает. Это обходится путем более явного указания пути в msgtool, вроде "/tmp/msgtool", или даже запроса пути из командной строки вместе с остальными аргументами. /**************************************************************************** Excerpt from "Linux Programmer's Guide - Chapter 6" (C)opyright 1994-1995, Scott Burkett **************************************************************************** MODULE: msgtool.c **************************************************************************** Средство командной строки для работы со очередями сообщений в стиле SysV ****************************************************************************/ #include #include #include #include #include #include #define MAX_SEND_SIZE 80 struct mymsgbuf { long mtype; char mtext[MAX_SEND_SIZE]; }; void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text); void read_message(int qid, struct mymsgbuf *qbuf, long type); void remove_queue(int qid); void change_queue_mode(int qid, char *mode); void usage(void); int main(int argc, char *argv[]) { key_t key; int msgqueue_id; struct mymsgbuf qbuf; if(argc == 1) usage(); /* Создаем уникальный ключ через вызов ftok() */ key = ftok(".",'m'); /* Открываем очередь - при необходимости создаем */ if((msgqueue_id = msgget(key, IPC_CREAT|0660)) == -1) { perror("msgget"); exit(1); } switch(tolower(argv[1][0])) { case 's': send_message(msgqueue_id, (struct mymsg buf *)&qbuf, atol(argv[2]), argv[3]); break; case 'r': read_message(msgqueue_id, &qbuf, atol(argv[2])); break; case 'd': remove_queue(msgqueue_id); break; case 'm': change_queue_mode(msgqueue_id, argv[2]); break; default: usage(); } return(0); } void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text) { /* Посылаем сообщение в очередь */ printf("Sending a message ...\n"); qbuf->mtype = type; strcopy(qbuf->mtext, text); if((msgsnd(qid, (struct msgbuf *)qbuf, strlen(qbuf->mtext)+1, 0)) == -1) { perror("msgsnd"); exit(1); } } void read_message(int qid, struct mymsgbuf *qbuf, long type) { /* Вычитываем сообщение из очереди */ printf("Reading a message ...\"); qbuf->mtype = type; msgrcv(qid, (struct msgbuf *)qbuf, MAX_SEND_SIZE, type, 0); printf("Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext); } void remove_queue(int qid) { /* Удаляем очередь */ msgctl(qid, IPC_RMID, 0); } void change_queue_mode(int qid, char *mode) { struct msqid_ds myqueue_ds; /* Получаем текущее состояние */ msgctl(qid, IPC_STAT, &myqueue_ds); /* Меняем состояние в копии внутренней структуры данных */ sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode) /* Обновляем состояние в самой внутренней структуре данных */ msgctl(qid, IPC_SET, &myqueue_ds); } void usage(void) { fprintf(stderr, "msgtool - A utility for tinkering with msg queues\n"); fprintf(stderr, "\nUSAGE: msgtool (s)end \n"); fprintf(stderr, " (r)ecv \n"); fprintf(stderr, " (d)elete\n"); fprintf(stderr, " (m)ode \n"); exit(1); }

| |

 




Начало  Назад  Вперед