Ao ler as páginas de manual nas chamadas read()
e write()
, parece que essas chamadas são interrompidas por sinais, independentemente de terem ou não de bloquear.
Em particular, suponha
- um processo estabelece um manipulador para algum sinal.
- um dispositivo é aberto (por exemplo, um terminal) com o
O_NONBLOCK
não configurado (ou seja, operando no modo de bloqueio) - o processo faz uma
read()
chamada de sistema para ler do dispositivo e, como resultado, executa um caminho de controle do kernel no espaço do kernel. - enquanto o precess está executando seu
read()
no espaço do kernel, o sinal para o qual o manipulador foi instalado anteriormente é entregue a esse processo e seu manipulador de sinal é invocado.
Lendo as páginas de manual e as seções apropriadas no SUSv3 'System Interfaces volume (XSH)' , verifica-se que:
Eu. Se a read()
for interrompido por um sinal antes de ler quaisquer dados (ou seja, ele teve que bloquear porque não havia dados disponíveis), ele retornará -1 com errno
definido como [EINTR].
ii. Se a read()
for interrompido por um sinal após a leitura bem-sucedida de alguns dados (ou seja, foi possível iniciar o atendimento da solicitação imediatamente), ele retornará o número de bytes lidos.
Pergunta A):
Estou correto ao assumir que, em ambos os casos (bloco / sem bloco), a entrega e o manuseio do sinal não são totalmente transparentes para o read()
?
Caso i. parece compreensível, pois o bloqueio read()
normalmente colocaria o processo no TASK_INTERRUPTIBLE
estado, de modo que, quando um sinal é entregue, o núcleo coloca o processo no TASK_RUNNING
estado.
No entanto, quando read()
não precisa bloquear (caso ii.) E está processando a solicitação no espaço do kernel, eu pensaria que a chegada de um sinal e seu manuseio seriam transparentes, assim como a chegada e o manuseio adequado de um HW interrupção seria. Em particular, eu teria assumido que, após a entrega do sinal, o processo seria temporariamente colocado no modo de usuário para executar seu manipulador de sinal, do qual retornaria eventualmente para terminar o processamento da interrupção read()
(no espaço do kernel) para que a read()
execução fosse executada. curso até a conclusão, após o qual o processo retorna ao ponto logo após a chamada para read()
(no espaço do usuário), com todos os bytes disponíveis lidos como resultado.
Mas ii. parece implicar que o read()
item seja interrompido, já que os dados estão disponíveis imediatamente, mas ele retorna apenas alguns dos dados (em vez de todos).
Isso me leva à minha segunda (e final) pergunta:
Pergunta B):
Se minha suposição em A) está correta, por que a read()
interrupção é interrompida, mesmo que não precise ser bloqueada porque há dados disponíveis para satisfazer a solicitação imediatamente? Em outras palavras, por que o read()
não é retomado após a execução do manipulador de sinal, resultando no retorno de todos os dados disponíveis (que estavam disponíveis, afinal)?