Після читання довідкових сторінок на дзвінках read()
та write()
дзвінках видно, що ці дзвінки перериваються сигналами незалежно від того, чи потрібно їх блокувати чи ні.
Зокрема, припустимо
- процес встановлює обробник для деякого сигналу.
- пристрій відкрито (скажімо, термінал) з
O_NONBLOCK
не встановленим (тобто працює в режимі блокування) - Потім процес робить
read()
системний виклик для зчитування з пристрою і в результаті виконує шлях управління ядром у просторі ядра. - в той час як прецесія виконує його
read()
в просторі ядра, сигнал, для якого обробник був встановлений раніше, передається до цього процесу і викликається його обробник сигналу.
Читаючи підручні сторінки та відповідні розділи у SUSv3 "Об'єм системних інтерфейсів (XSH)" , можна виявити , що:
i. Якщо read()
сигнал переривається сигналом, перш ніж він зчитує будь-які дані (тобто його потрібно було заблокувати, оскільки відсутні дані), він повертає -1 із errno
встановленим на [EINTR].
ii. Якщо read()
сигнал переривається сигналом після того, як він успішно прочитав деякі дані (тобто можна було негайно почати обслуговування запиту), він повертає кількість прочитаних байтів.
Питання A):
Чи правильно я вважаю, що в будь-якому випадку (блок / блок) подача та обробка сигналу не є повністю прозорою для read()
?
Справа i. здається зрозумілим, оскільки блокування read()
звичайно розміщує процес у TASK_INTERRUPTIBLE
стані, так що коли сигнал подається, ядро переводить процес у TASK_RUNNING
стан.
Однак, коли read()
не потрібно блокувати (випадок II.) І обробляти запит у просторі ядра, я б подумав, що надходження сигналу та його обробка буде прозорим, як і прихід і правильне поводження з HW переривання було б. Зокрема, я вважав би, що після доставки сигналу процес буде тимчасово переведений в режим користувача, щоб виконати його обробник сигналу, з якого він повернеться в кінцевому підсумку, щоб закінчити обробку перерваного read()
(в ядрі-просторі), щобread()
запустити його Курс до завершення, після чого процес повертається до пункту одразу після виклику до read()
(у користувальницькому просторі), у результаті чого всі наявні байти читаються.
Але іі. Здається, означає, щоread()
це перервано, оскільки дані доступні негайно, але вони повертають, повертає лише деякі дані (замість усіх).
Це підводить мене до мого другого (і остаточного) питання:
Питання B):
Якщо моє припущення під пунктом A) правильне, чому read()
переривання переривається, хоча його не потрібно блокувати, оскільки доступні дані для задоволення запиту негайно? Іншими словами, чому read()
після відновлення обробника сигналу не поновлюється, зрештою, в результаті повертаються всі наявні дані (які були доступні врешті)?