Из чтения страниц справочника по вызовам read()
и write()
вызовам выясняется, что эти вызовы прерываются сигналами независимо от того, должны они блокировать или нет.
В частности, предположим
- процесс устанавливает обработчик для некоторого сигнала.
- устройство открыто (скажем, терминал) с
O_NONBLOCK
не установленным (т.е. работает в режиме блокировки) - затем процесс выполняет
read()
системный вызов для чтения с устройства и в результате выполняет путь управления ядром в пространстве ядра. - в то время как прецесс выполняет его
read()
в пространстве ядра, сигнал, для которого был установлен ранее обработчик, доставляется этому процессу, и вызывается его обработчик сигнала.
Читая справочные страницы и соответствующие разделы SUSv3 «Объем системных интерфейсов (XSH)» , можно обнаружить, что:
я. Если a read()
прервано сигналом до того, как он прочитает какие-либо данные (т. errno
Е. Ему пришлось заблокировать, потому что данные не были доступны), он возвращает -1 с установленным на [EINTR].
II. Если a read()
прервано сигналом после того, как он успешно прочитал некоторые данные (т. Е. Было возможно немедленно начать обслуживание запроса), он возвращает количество прочитанных байтов.
Вопрос A):
Правильно ли предположить, что в любом случае (блок / нет блока) доставка и обработка сигнала не полностью прозрачны для read()
?
Случай I. кажется понятным, поскольку блокировка read()
обычно переводит процесс в TASK_INTERRUPTIBLE
состояние, так что при доставке сигнала ядро переводит процесс в TASK_RUNNING
состояние.
Однако, когда read()
блок не нужно блокировать (случай ii.) И обрабатывает запрос в пространстве ядра, я бы подумал, что поступление сигнала и его обработка будут прозрачными во многом как поступление и правильная обработка HW Прерывание будет. В частности, я бы предположил, что после доставки сигнала процесс будет временно переведен в пользовательский режим для выполнения его обработчика сигнала, из которого он в конечном итоге вернется, чтобы завершить обработку прерванного read()
(в пространстве ядра), чтобы read()
запустить его переход к завершению, после которого процесс возвращается к точке сразу после вызова read()
(в пользовательском пространстве) со всеми доступными байтами, считанными в результате.
Но ii. кажется, подразумевает, что read()
прервано, поскольку данные доступны сразу, но он возвращает возвращает только некоторые данные (вместо всех).
Это подводит меня ко второму (и последнему) вопросу:
Вопрос B):
Если мое предположение в соответствии с пунктом А) является верным, почему read()
прерывание происходит, даже если ему не нужно блокировать, потому что есть данные, доступные для немедленного удовлетворения запроса? Другими словами, почему read()
не возобновляется после выполнения обработчика сигнала, что в конечном итоге приводит к возвращению всех доступных данных (которые были доступны в конце концов)?