|
Программирование >> Структура ядра и системные вызовы
в следующем примере показано, как открывается и создается (при необходимости) очередь сообщений /foo с доступом для чтения и записи. Разрешение на чтение-запись для вновь создаваемой очереди устанавливается только по категории владелец . В новой очереди может находиться до 200 сообщений, длина каждого из которых не должна превышать 1024 байтов... содержит атрибуты для новой очереди в очереди может находиться максимум 200 сообщений максимум 1024 байта в одном сообщении struct mq attr attrv; attrv.mq maxmsg = 200; attrv.mq msgsize = 1024; attrv.mq flags =0; mqcl t mqid = mq open( /foo , 0 RDWR I 0 CREAT, S IRWXU, Sattrv); if (mqid== (mq t)-l) perror( mq open ); API mq send передает сообщение в очередь, указанную аргументом mqid. Значение аргумента msg - это адрес буфера, который содержит текст сообщения, аргумент len задает размер текста сообщения (количество символов). Значение len должно быть меньше лимита, установленного для данной очереди сообщений (максимального размера сообщения). В противном случае вызов не будет выполнен. Значение аргумента priority - это целое число из диапазона от О до M0 PRIO MAX. Оно используется для сортировки сообщений, имеющихся в очередях, при этом сообщения с более высоким значением priority обрабатываются в первую очередь. Если у двух и более сообщений одинаковое значение priority, они сортируются в порядке убывания их времени нахождения в очереди - старые сообщения извлекаются раньше, чем новые. В случае успешного выполнения эта функция возвращает О, а в случае неудачи--1. Отметим, что данная функция может блокировать вызывающий процесс, если очередь сообщений уже полна. Если же очередь была открыта с флагом 0 NONBLOCK, функция прерывается и немедленно возвращает код неудачного завершения, -1. В следующем примере сообщение Hello POSIX.Ib передается в очередь сообщений, указанную аргументом mqid, с приоритетом 5: char* msg = Hello POSIX.Ib ; if (mq send(mq id, msg, strlen(msg)+1, 5)) perror( mq send ); API mq receive принимает самое старое и имеющее наивысший приоритет сообщение из очереди сообщений, указанной аргументом mqid. Значение аргум:ента buf - адрес буфера, который содержит текст сообщения, аргумент len задает максимальный размер буфера buf. Если размер принимаемого сообщения больше len байтов, эта функция возвращает код неудачного завершения. Аргумент prio - это адрес целочисленной беззнаковой переменной, содержащей значение приоритета принимаемого сообщения. Если значение этого аргумента задано как NULL, то приоритет принимаемого сообщения роли не играет. В случае успешного выполнения данная функция возвращает количество байтов текста сообщения, помещенных в буфер buf а в случае неудачи -1. Если очередь сообщений пуста, функция может заблокировать вызывающий процесс. В ситуации же, когда очередь была открыта с флагом 0 NONBLOCK, функция прерывается и немедленно возвращает код -1. Если вызов mq receive блокирует несколько процессов, то прибывшее в очередь сообщение будет получено процессом, имеющим наивысший приоритет и дольше других ожидающим поступления сообщения. В следующем примере принимается сообщение из очереди, указанной аргументом mqid: char buf[256]; unsigned prio; ; if (mq receive( mqid, buf, sizeof buf, iprio )== -1) perror( mq receive ); cerr receive msg: buf , priority- prio endl; API mqclose освобождает ресурсы, использованные при открытии очереди сообщений с заданным идентификатором сообщения, mqid. В случае успешного выполнения эта функция возвращает О, а в случае неудачи -1. API mq notify используется в том случае, если процесс должен получить асинхронное уведомление о прибытии сообщения в пустую очередь, а не блокироваться вызовом mqreceive в ожидании такого события. Аргумент mqid указывает очередь, в которой нужно контролировать прибытие сообщений. Значение аргумента sigvp - это адрес переменной типа struct sigevent. Тип данных struct sigevent определяется в заголовке <signal.h> и содержит номер сигнала, который должен генерироваться вызывающим процессом при прибытии сообщения в указанную очередь. Если существует процесс, который уже получил уведомление или заблокирован вызовом mqreceive, данная функция не выполняется. Более того, даже если процесс успешно выполнил вызов mq notify и сигнал уведомления доставлен (поскольку сообщение поступило в очередь), он все равно может не принять сообщение, если какой-то другой процесс вызовет mqreceive раньше. Наконец, если значение аргумента sigvp задано как NULL, вызов mqjiotify отменяет отправку уведомления для указанной очереди сообщений. Такое уведомление не отправляется также в том случае, если процесс уже существует или вызывает для данной очереди сообщений API mqjclose. В случае успешного выполнения эта функция возвращает О, а в случае неудачи--1. В следующем примере регистрируется сигнал SIGUSRl, который должен быть доставлен в вызывающий процесс в случае прибытия сообщения в очередь, указанную переменной mqid: struct sigevent sigv; sigv.sigev notify = SIGEV SIGNAL; запрос уведомления sigv.sigev signo = SIGUSRl; послать SIGUSRl для уведомления If <mq notify(mqid, isigv)==-l) perror( mq notify ); API mq getattr запрашивает атрибуты очереди сообщений, указанной аргументом mqid. Аргумент attrp - это адрес переменной типа struct mqattr. Тип данных struct mqattr определяется в заголовке <mqueue.h>. Вот некоторые полезные поля этой структуры. Поле Содержание
В случае успешного выполнения эта функция возвращает О, а в случае неудачи -1. В следующем примере программа получает информацию об атрибутах очереди сообщений, указанной переменной mqid: struct mq attr attrv; if {mq getattr(mqid, &attrv)==-l) perror{ mq getattr ); else cout flags = attrv.mq flags , cur. no. msg attrv.mq curmsgs endl; API mqjsetattr устанавливает атрибут mq attr::mq Jlags для очереди сообщений, указанной аргументом mqid. Аргумент attrp - это адрес переменной типа struct mqjattr. API mq setattr использует только значение attrp- >mq flags. Допустимое значение этого поля - О (блокирующая операция над очередью) или 0 NONBLOCK (неблокирующая операция над очередью). С помощью аргумента oattrp, задающего адрес переменной типа struct mqattr, возвращается та же информация, что и при вызове mq getattr. В случае успешного выполнения эта функция возвращает О, а в случае неудачи -1. В следующем примере мы задаем выполнение неблокирующих операций над очередью сообщений, обозначенной переменной mqid. Старые атрибуты очереди игнорируются. struct mq attr atrrv; attrv.mq+flags = 0 NONBLOCK; if (mq setattr{mqid, Sattrv, 0}==-!} perror{ mq setattr ); 10.4.1. Класс message стандарта POSIX.lb Класс сообщений, определенный в разделе 10.3.7, предназначен для обработки сообщений только ОС UNIX System V. В следующем заголовке messagel.h определяется новый класс сообщений, в котором используются API сообщений стандарта POSIX. lb. Следует отметить, что интерфейс этого нового класса идентичен интерфейсу, приведенному в разделе 10.3.7: fifndef MESSAGE2 H ♦define MESSAGE2 H ♦include <stdio.h.> ♦include <memory.h> finclude <sys/ipc.h> finclude <mqueue.h> использовать API сообщений POSIX.lb /* общие объявления для серверного процесса */ enum { MSGKEY=186, MAX LEN=256, ILLEGAL CMD =4); enum { LOCAL TIME = 1, UTC TIME = 2, QU1T CMD => 3 }; struct mgbuf long char mtype; mtext [MAX LEN]; /* класс сообщений POSIX.lb */ class message private: mqd t msgid; идентификатор очереди сообщений struct mgbuf mObj; public: /* функция-конструктор, совместимая с System V */ message( int key ] char name[80}; sprintf(name, /MQUEUE%d ,key); if ({msgId=mq open(name,0 RDWRIPC CREAT,0666,0)}==(mqd tl-l} perror( mq open ) ; /* функция-конструктор, соответствующая POSIX.lb */ message( const char* name } /* функция-деструктор */ ТГ , -message О { (void)mq close { msgId}; /* проверить статус открытия очереди */ int good О ( return (msgId >= 0} ? 1 : Oy }; /* удалить очередь сообщений */ .i. int rmQ О li , return mq close( msgid ); /* передать сообщение * I .-;> J int send( const void*, buf, int pze, int type) mObj.mtype = type; memcpy{mObj.mtext,buf,size); if (mq send{msgld,(char*)&mObj,size,type)) { perror{ mq send ); return -1; return 0; /* принять сообщение */ int rcv{ void* buf, int size, int type, unsigned* rtype) struct mq attr attrv; if {mq getattr{msgld,&attrv)= -l) { perror{ mq getattr ) ; return -1; if {!attrv.mq curmsgs) return -1; сообщений нет int len = mq receive(msgld,(char*)&mObj,MAX LEN,rtype); if (len < 0) { perror{ mq receieve ); return -2; if (type && {(type > 0 S& type!=*rtype) 11 (type < 0 S& -type < *rtype))) { mq send{msgld, (char*)SmObj, len, *rtype ); return -3; не тот тип memcpy{buf,mObj.mtext,len) ; return len; #endif /* MESSAGE2 H */ Версия класса message, определенная в стандарте POSIX.Ib, может использоваться так же, как версия, принятая в System V. В частности, есть две функции-конструктора messager.message, одна из которых вызывается с целочисленным ключом, а другая с именем сообщения. В любом случае для открытия и создания (в случае необходимости) очереди сообщений вызывается функция mq open. Функции messager.send, message::rcv и message:: message имеют такой же интерфейс, что и соответствующие функции в классе message в System V. Единственное различие заключается в том, что функция message::rcv стандарта POSIX.Ib не может выбирать сообщения на основании заданного пользователем типа. Эта функция получает из очереди сообщение с наивысшим приоритетом. Если тип сообщения не соответствует типу, указанному пользователем, эта функция помещает сообщение обратно в очередь и возвращает -1. Тип сообщения соответствует типу, определенному пользователем, если: 1) заданный пользователем тип - О <т.е. тип сообщения значения не имеет); 2) определенный пользователем тип полностью совпадает с типом принятого сообщения; 3) указанный пользователем тип отрицателен, а абсолютная величина его целочисленного значения больше значения типа принятого сообщения или равна ему. Заголовок message2.h можно использовать в тех же клиентской и серверной программах, которые описаны в разделе 13.3.7. Результаты выполнения скомпилированных клиентской и серверной программ должны совпадать с аналогичными результатами для версии System V. 10.5. Семафоры в UNIX System V Семафоры - это средства синхронизации выполнения множества процессов. Семафоры группируются в наборы, каждый из которых содержит один и более семафоров. Семафоры часто используются совместно с разделяемой памятью, реализуя таким образом мощный метод межпроцессного взаимодействия. API семафоров ОС UNIX System V выполняют следующие функции: создают набор семафоров; открывают набор семафоров и получают дескриптор, обозначающий данный набор; увеличивают и уменьшают целочисленные значения одного и боле? семафоров в наборе; запрашивают значения одного и более семафоров в наборе; 1П запрашивают и устанавливают управляющие параметры набора семафоров. Значением семафора является переменная типа unsigned short. Процесс, имеющий право на чтение семафоров, может запрашивать их значения. Процесс, имеющий право на изменение семафоров, может увеличивать и уменьшать их значения. Если процесс попытается уменьшить значение семафора так, чтобы оно стало отрицательным, эта операция и сам процесс будут заблокированы до тех пор, пока другой процесс не увеличит значение данного семафора до величины, достаточной для успешного выполнения операции заблокированного процесса (т.е. чтобы значение семафора после операции уменьшения было положительным или равным нулю). Этот принцип лежит в основе синхронизации процессов с помощью семафоров: процесс X, который должен дождаться выполнения процессом Y опреде-ленных действий, уменьшает значение одного или нескольких семафоров на некоторую величину, в результате чего блокируется ядром;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.004
При копировании материалов приветствуются ссылки. |