Dalla lettura delle pagine man su read()
e write()
chiamate sembra che queste chiamate vengano interrotte da segnali indipendentemente dal fatto che debbano essere bloccati o meno.
In particolare, supponiamo
- un processo stabilisce un gestore per alcuni segnali.
- un dispositivo viene aperto (per esempio un terminale) con il
O_NONBLOCK
non impostato (cioè operando in modalità di blocco) - il processo quindi effettua una
read()
chiamata di sistema per leggere dal dispositivo e di conseguenza esegue un percorso di controllo del kernel nello spazio kernel. - mentre il precesso sta eseguendo il suo
read()
nello spazio kernel, il segnale per il quale il gestore è stato installato in precedenza viene consegnato a quel processo e il suo gestore del segnale viene invocato.
Leggendo le pagine man e le sezioni appropriate in SUSv3 'System Interfaces volume (XSH)' , si scopre che:
io. Se a read()
viene interrotto da un segnale prima di leggere qualsiasi dato (cioè deve bloccarsi perché non erano disponibili dati), restituisce -1 con errno
impostato su [EINTR].
ii. Se a read()
viene interrotto da un segnale dopo aver letto correttamente alcuni dati (ovvero è stato possibile iniziare immediatamente a servire la richiesta), restituisce il numero di byte letti.
Domanda A):
ho ragione a supporre che in entrambi i casi (blocco / nessun blocco) la consegna e la gestione del segnale non siano completamente trasparenti al read()
?
Caso I. sembra comprensibile poiché il blocco read()
normalmente posizionerebbe il processo nello TASK_INTERRUPTIBLE
stato in modo tale che quando un segnale viene consegnato, il kernel pone il processo nello TASK_RUNNING
stato.
Tuttavia, quando read()
non è necessario bloccare (caso ii.) Ed è in fase di elaborazione della richiesta nello spazio kernel, avrei pensato che l'arrivo di un segnale e la sua gestione sarebbero stati trasparenti proprio come l'arrivo e la corretta gestione di un HW l'interruzione sarebbe. In particolare avrei assunto che al momento della consegna del segnale, il processo sarebbe stato messo temporaneamente in modalità utente ad eseguire il suo gestore di segnale da cui sarebbe tornato alla fine per finire l'elaborazione del interrotta read()
(nello spazio del kernel) in modo che l' read()
esegue il suo ovviamente, al termine del quale il processo ritorna al punto immediatamente successivo alla chiamata read()
(nello spazio utente), con la lettura di tutti i byte disponibili.
Ma ii. sembra implicare che read()
sia interrotto, poiché i dati sono immediatamente disponibili, ma restituisce restituisce solo alcuni dei dati (anziché tutti).
Questo mi porta alla mia seconda (e ultima) domanda:
Domanda B):
se la mia ipotesi in A) è corretta, perché read()
viene interrotta, anche se non è necessario bloccare perché ci sono dati disponibili per soddisfare immediatamente la richiesta? In altre parole, perché read()
non viene ripreso dopo aver eseguito il gestore del segnale, risultando infine nella restituzione di tutti i dati disponibili (che erano disponibili dopo tutto)?