Interrupção de chamadas do sistema quando um sinal é capturado

0

A partir da leitura das páginas man nas chamadas 'read ()' e 'write ()', parece que essas chamadas são interrompidas por sinais, independentemente de terem que bloquear ou não.

Em particular, assuma

  • um processo estabelece um manipulador para algum sinal.
  • um dispositivo é aberto (digamos, um terminal ....) com o 'O_NONBLOCK' NÃO definido (ou seja, operando no modo de bloqueio)
  • o processo então faz uma chamada de sistema 'read ()' 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 man pages e as seções apropriadas no SUSv3 'System Interfaces Volume (XSH)', descobre-se que:

i. Se uma leitura () for interrompida por um sinal antes de ler qualquer dado (isto é, tiver que ser bloqueado porque não há dados disponíveis), ele retornará -1 com 'errno' configurado para [EINTR].

ii. Se uma leitura () for interrompida por um sinal depois de ter lido com sucesso alguns dados (ou seja, foi possível iniciar imediatamente a solicitação da solicitação), ele retornará o número de bytes lidos

Pergunta A):

Estou correto em assumir que, em ambos os casos (bloco / nenhum 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 estado 'TASK_INTERRUPTIBLE' para que, quando um sinal fosse entregue, o kernel colocasse o processo no estado 'TASK_RUNNING'.

No entanto, quando o 'read ()' não precisa bloquear (case ii.) e está processando a requisição no kernel-space, eu teria pensado que a chegada de um sinal e sua manipulação seria transparente como a chegada e manuseio adequado de uma interrupção HW seria. Em particular, eu teria assumido que, após a entrega do sinal, o processo seria colocado temporariamente no USER-MODE para executar seu manipulador de sinal do qual ele retornaria eventualmente para terminar o processamento do interrompido 'read ()' (no kernel-space ) para que o 'read ()' siga seu curso até a conclusão, após o qual o processo retorna ao ponto imediatamente 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 ()' é interrompido, uma vez que os dados estão disponíveis imediatamente MAS retorna retornos 'alguns' dos dados (em vez de todos).

Isso me leva à minha segunda (e última) pergunta

Pergunta B):

Se minha suposição sob A) estiver correta, por que o 'read ()' é interrompido, mesmo que não precise ser bloqueado 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 sinais, eventualmente resultando na devolução de todos os dados disponíveis (que foram disponibilizados afinal)?

    
por darbehdar 11.07.2011 / 07:29

1 resposta

0

Há uma discussão interessante sobre isso na página Filosofia do Unix . Basicamente, simplifica o design do kernel. Eu acredito que o * BSD tem a opção de reiniciar automaticamente as chamadas do sistema interrompidas. Mas no Linux você tem que escrever uma função de wrapper para lidar com isso.

    
por 11.07.2011 / 07:55

Tags