Внутреннее устройство ядра Linux 2.4

Sys_msgrcv()


На вход функции sys_msgrcv() передаются ID очереди (msqid), указатель на буфер типа (msgp), предполагаемый размер сообщения (msgsz), тип сообщения (msgtyp) и флаги (msgflg). Функция, по очереди ожидающих сообщений, ищет сообщение с заданным типом и первое же найденное сообщение копирует в пользовательский буфер. Если сообщения с заданным типом не обнаружено, то процесс-получатель заносится в очередь ожидания для процессов-получателей и остается там до тех пор, пока не будет получено ожидаемое сообщение. Более подробное описание действий функции sys_msgrcv() приводится ниже:

  • В первую очередь вызывается функция , которая устанавливает режим поиска, исходя из значения msgtyp. Далее выполняется глобальная блокировка очереди сообщений и находится дескриптор очереди по заданному ID. Если искомая очередь сообщений не найдена, то возвращается код ошибки EINVAL.
  • Проверяются права доступа текущего процесса.
  • Для каждого сообщения, начиная с первого, в очереди ожидающих сообщений вызывается , которая проверяет тип сообщения на соответствие заданному. Поиск продолжается до тех пор пока искомое сообщение не будет найдено либо пока не будет встречен конец очереди. Если режим поиска задан как SEARCH_LESSEQUAL, то результатом поиска будет первое же встретившееся сообщение с типом равным или меньшим msgtyp.
  • Если сообщение, удовлетворяющее критериям поиска, было найдено, то далее выполняются следующие действия:

  • Если размер сообщения больше чем ожидаемый и установлен флаг MSG_NOERROR, то глобальная блокировка снимается и в вызывающий процесс передается код E2BIG.
  • Сообщение удаляется из очереди ожидающих сообщений и обновляются статистики очереди сообщений.
  • Активируются процессы, находящиеся в очереди ожидания для процессов-отправителей. Удаление сообщения из очереди на предыдущем шаге делает возможным продолжить работу одному из процессов-отправителей. Переход к выполнению операций (к п. 10)
  • Если сообщение не было найдено, то проверяется msgflg. Если установлен флаг IPC_NOWAIT, то глобальная блокировка снимается и вызывающему процессу возвращается код ENOMSG. В противном случае процесс помещается в очередь ожидания для процессов-получателей:




    1. В памяти размещается новая структура msr и добавляется в начало очереди ожидания.


    2. В поле r_tsk в msr заносится указатель на текущий процесс.


    3. В поле r_msgtype и r_mode

      заносятся ожидаемый тип сообщения и режим поиска соответственно.


    4. Если установлен флаг MSG_NOERROR, то в поле r_maxsize заносится значение из msgsz, в противном случае - значение INT_MAX.


    5. В поле r_msg заносится признак того, что сообщение не найдено.


    6. После завершения инициализации, процесс приобретает статус TASK_INTERRUPTIBLE, глобальная блокировка очереди сообщений снимается и вызывается планировщик schedule().


    7. После активизации ожидающего процесса сразу же проверяется поле r_msg. Это поле содержит либо сообщение переданное напрямую, либо код ошибки. Если поле содержит сообщение то далее переходим к операциям (к п. 10). В противном случае - опять выполняется глобальная блокировка.


    8. После того как блокировка установлена, поле r_msg проверяется еще раз. Если в процессе установки блокировки было получено сообщение, то производится переход к операциям (к п. 10).


    9. Если поле r_msg осталось без изменений, то, следовательно, процесс был активирован для выполнения повторной попытки получить сообщение. Проверяется наличие необработанных сигналов для данного процесса и если таковые имеются, то глобальная блокировка снимается и процессу возвращается код EINTR. Иначе - производится попытка получить сообщение.


    10. Если поле r_msg содержит код ошибки, то снимается глобальная блокировка и процессу передается ошибка.


    11. После проверки адреса пользовательского буфера msp, тип сообщения записывается в mtype и содержимое сообщения копируется в поле mtext функцией . И в заключение освобождается память вызовом функции .



    12. Содержание раздела