
- •Определение идентификаторов узла, процесса и канала (nd/pid/chid) нужного сервера.
- •Обмен длинными сообщениями
- •Обмен составными сообщениями
- •Сообщения типа «импульс» (pulse)
- •Функция MsgDeliverEvent()
- •Флаги канала
- •Обмен сообщениями в сети
- •Преимущества очередей сообщений стандарта posix
- •Функция Описание
- •Именованные каналы
Обмен составными сообщениями
Функции:
SETIOV(iov, addr, len);
MsgSendv (int coid, const siov, int sparts, const riov, int rparts);
MsgReceivev (int chid, const riov, int rparts, struct _msg_info *info );
Функция SETIOV() содержит два элемента — адрес и длину.
Функции MsgSendv () и MsgReceivev () имеют почти те же самые аргументы, что и функции MsgSend() и MsgReceive(), рассмотренные ранее.
Аргументы:
sparts и rparts указывают число передаваемых и принимаемых частей;
siov и riov указывают на адреса заголовков передаваемого и принимаемого сообщений.
Замечания:
•Число фрагментов ограничено значением 231.
•Ядро просто копирует данные, указанные вектором IOV, из одного адресного пространства в другое.
•Вектор-источник и вектор-приемник не должны совпадать.
Для передачи составного сообщения серверу клиент должен сделать так:
// Настроить структуру IOV для передачи:
SETIOV (iov +0, header, 12);
SETIOV (iov +1, sbuffer, 12000);
MsgSendv (coid, siov, 2, riov, 1);
Для приема сообщения клиента сервер файловой системы должен сделать так:
// Настроить структуру IOV для приема:
SETIOV (iov +0, header, sizeof (header));
SETIOV (iov +1, cache-buffer [37], 4096);
SETIOV (iov +2, cache-buffer [16], 4096);
SETIOV (iov +3, cache-buffer [22], 4096);
rcvid = MsgReceivev (chid, iov, 4, NULL);
Эта программа задает вектор IOV из 4 частей, первая из которых указывает на заголовок, а следующие три части — на блоки кэш-памяти с номерами 37, 16 и 22.
Но в общем случае мы должны заголовок принять отдельно, а затем задать вектор IOV из 3 частей.
// Настроить структуру IOV для приема:
SETIOV (iov +0, cache-buffer [37], 4096);
SETIOV (iov +1, cache-buffer [16], 4096);
SETIOV (iov +2, cache-buffer [22], 4096);
MsgReceive (chid, header, sizeof (header), NULL);
switch (header.message_type)
{
case _IO_WRITE:
number_of_bytes - header.io_write.nbytes;
// Выделить / найти элемент кэша
// Заполнить элементы кэша 3-элементным IOV
MsgReadv (rcvid, iov, 3, sizeof (header.io_write|);
…………………………………………………………..
}
Возможные действия сервера в ответ на запрос чтения:
1. Найти элементы кэша, которые соответствуют запрашиваемым данным.
2. Заполнить вектора IOV ссылками на них.
3. Применить функцию MsgWritev() (или MsgReplyv()) для передачи данных клиенту.
Семейство функций MsgSend*() содержит четыре основных варианта реализации с точки зрения буферов источника и адресата, плюс два варианта собственно системного вызова — итого восемь.
Функция Буфер передачи Буфер приема
MsgSend() |
линейный |
линейный |
MsgSendnc() |
линейный |
линейный |
MsgSendsv() |
линейный |
IOV |
MsgSendsvnc() |
линейный |
IOV |
MsgSendvs() |
IOV |
линейный |
MsgSendvsnc() |
IOV |
линейный |
MsgSendv() |
IOV |
IOV |
MsgSendvnc() |
IOV |
IOV |
Функции MsgSendsv() и MsgSendsvnc() идентичны только по части параметров. Различие заключается в том, что функция с суффиксом «nc» (no cancellation») ) не являются точками завершения, в то время как версии без этого суффикса — являются.