Из чтения справочных страниц по вызовам read() и write() выясняется, что эти вызовы прерываются сигналами независимо от того, должны они блокировать или нет.

В частности, предположим,

  • процесс устанавливает обработчик для некоторого сигнала.
  • устройство открыто (скажем, терминал ....) с НЕ установленным параметром O_NONBLOCK (т.е. работает в режиме блокировки)
  • затем процесс выполняет системный вызов read () для чтения с устройства и в результате выполняет путь управления ядром в пространстве ядра.
  • в то время как прецесс выполняет свое read () в пространстве ядра, сигнал, для которого был установлен ранее обработчик, доставляется этому процессу, и вызывается его обработчик сигнала.

Читая справочные страницы и соответствующие разделы SUSv3 «Объем системных интерфейсов (XSH)», можно обнаружить, что:

я. Если read() прерывается сигналом до того, как он прочитает какие-либо данные (т. Е. Ему пришлось заблокировать, потому что данные не были доступны), он возвращает -1 с errno, установленным в [EINTR].

II. Если read() прерывается сигналом после того, как он успешно прочитал некоторые данные (т.е. можно было немедленно начать обслуживание запроса), он возвращает количество прочитанных байтов.

Вопрос А):

Правильно ли я предположить, что в любом случае (блок / нет блока) доставка и обработка сигнала не полностью прозрачны для read ()?

Случай я. кажется понятным, поскольку блокировка read() обычно переводит процесс в состояние «TASK_INTERRUPTIBLE», так что при доставке сигнала ядро переводит процесс в состояние «TASK_RUNNING».

Однако, когда read() не нужно блокировать (случай ii.) И обрабатывает запрос в пространстве ядра, я бы подумал, что поступление сигнала и его обработка будут прозрачными во многом как поступление и правильная обработка прерывания HW будет. В частности, я бы предположил, что после доставки сигнала процесс будет временно помещен в USER-MODE для выполнения его обработчика сигнала, из которого он в конечном итоге вернется, чтобы завершить обработку прерванного read() (в пространстве ядра). ), так что read() завершает свой курс до завершения, после чего процесс возвращается к точке сразу после вызова read() (в пространстве пользователя), в результате чего все доступные байты считываются ,

Но ii. Кажется, подразумевается, что read() прервана, так как данные доступны сразу, НО возвращает «некоторые» данные (вместо всех).

Это подводит меня ко второму (и последнему) вопросу

Вопрос Б):

Если мое предположение в отношении А) верно, почему «read ()» прерывается, даже если ему не нужно блокировать, потому что есть данные, доступные для немедленного удовлетворения запроса? Другими словами, почему «read ()» не возобновляется после выполнения обработчика сигнала, что в конечном итоге приводит к возвращению всех доступных данных (которые были доступны для всех)?

1 ответ1

0

На странице философии Unix есть интересная дискуссия об этом. По сути, это упрощает дизайн ядра. Я считаю, что * BSD имеет возможность автоматически перезапускать прерванные системные вызовы. Но в Linux вы должны написать функцию-обертку, чтобы справиться с ней.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .