Sinal (IPC) - Signal (IPC)

Os sinais são mensagens padronizadas enviadas a um programa em execução para acionar um comportamento específico, como encerrar ou lidar com erros. Eles são uma forma limitada de comunicação entre processos (IPC), normalmente usados ​​em Unix , semelhantes ao Unix e outros sistemas operacionais compatíveis com POSIX .

Um sinal é uma notificação assíncrona enviada a um processo ou a um thread específico dentro do mesmo processo para notificá-lo de um evento. Os usos comuns de sinais são interromper, suspender, encerrar ou eliminar um processo. Os sinais se originaram na Bell Labs Unix dos anos 1970 e mais tarde foram especificados no padrão POSIX .

Quando um sinal é enviado, o sistema operacional interrompe o fluxo normal de execução do processo de destino para entregar o sinal. A execução pode ser interrompida durante qualquer instrução não atômica . Se o processo registrou anteriormente um manipulador de sinal , essa rotina é executada. Caso contrário, o manipulador de sinal padrão é executado.

Os programas incorporados podem encontrar sinais úteis para comunicações entre processos, pois os sinais são notáveis ​​por sua eficiência algorítmica .

Os sinais são semelhantes às interrupções , a diferença é que as interrupções são mediadas pela CPU e manipuladas pelo kernel, enquanto os sinais são mediados pelo kernel (possivelmente por meio de chamadas do sistema) e manipuladas por processos individuais . O kernel pode passar uma interrupção como um sinal para o processo que a causou (exemplos típicos são SIGSEGV , SIGBUS , SIGILL e SIGFPE ).

História

A versão 1 do Unix tinha chamadas de sistema separadas para detectar interrupções, quits e armadilhas de máquina. A versão 4 combinou todas as armadilhas em uma chamada, sinal e cada armadilha numerada recebeu um nome simbólico na versão 7 . kill apareceu na versão 2 e na versão 5 pode enviar sinais arbitrários. O plano 9 da Bell Labs substituiu os sinais por notas , que permitem o envio de strings curtas e arbitrárias.

Enviando sinais

A chamada de sistema kill (2) envia um sinal especificado para um processo especificado, se as permissões permitirem. Da mesma forma, o comando kill (1) permite que um usuário envie sinais aos processos. A função de biblioteca raise (3) envia o sinal especificado para o processo atual.

Exceções como divisão por zero ou violação de segmentação irão gerar sinais (aqui, SIGFPE "exceção de ponto flutuante" e SIGSEGV "violação de segmentação" respectivamente, que por padrão causam um dump de núcleo e uma saída do programa).

O kernel pode gerar sinais para notificar processos de eventos. Por exemplo, SIGPIPE será gerado quando um processo grava em um pipe que foi fechado pelo leitor; por padrão, isso faz com que o processo seja encerrado, o que é conveniente ao construir pipelines de shell .

Digitar certas combinações de teclas no terminal de controle de um processo em execução faz com que o sistema envie certos sinais:

  • Ctrl-C (em Unixes mais antigos, DEL) envia um sinal INT ("interrupção", SIGINT ); por padrão, isso faz com que o processo seja encerrado.
  • Ctrl-Z envia um sinal TSTP ("parada do terminal", SIGTSTP ); por padrão, isso faz com que o processo suspenda a execução.
  • Ctrl- \ envia um sinal QUIT ( SIGQUIT ); por padrão, isso faz com que o processo seja encerrado e despejado o núcleo.
  • Ctrl-T (não suportado em todos os UNIXes) envia um sinal INFO ( SIGINFO ); por padrão, e se suportado pelo comando, isso faz com que o sistema operacional mostre informações sobre o comando em execução.

Essas combinações de teclas padrão com sistemas operacionais modernos podem ser alteradas com o comando stty .

Sinais de tratamento

Os manipuladores de sinais podem ser instalados com a chamada do sistema signal (2) ou sigaction (2) . Se um manipulador de sinal não for instalado para um sinal específico, o manipulador padrão será usado. Caso contrário, o sinal é interceptado e o manipulador de sinais é invocado. O processo também pode especificar dois comportamentos padrão, sem criar um manipulador: ignorar o sinal (SIG_IGN) e usar o manipulador de sinal padrão (SIG_DFL). Existem dois sinais que não podem ser interceptados e tratados: SIGKILL e SIGSTOP .

Riscos

O manuseio de sinais é vulnerável às condições de corrida . Como os sinais são assíncronos, outro sinal (mesmo do mesmo tipo) pode ser entregue ao processo durante a execução da rotina de tratamento do sinal.

A chamada sigprocmask (2) pode ser usada para bloquear e desbloquear a entrega de sinais. Os sinais bloqueados não são entregues ao processo até serem desbloqueados. Sinais que não podem ser ignorados (SIGKILL e SIGSTOP) não podem ser bloqueados.

Os sinais podem causar a interrupção de uma chamada de sistema em andamento, deixando para o aplicativo gerenciar uma reinicialização não transparente .

Os manipuladores de sinais devem ser escritos de uma maneira que não resulte em quaisquer efeitos colaterais indesejados, por exemplo , alteração de errno , alteração de máscara de sinal, alteração de disposição de sinal e outras alterações de atributo de processo global . O uso de funções não reentrantes , por exemplo, malloc ou printf , dentro dos manipuladores de sinal também não é seguro. Em particular, a especificação POSIX e o sinal da página do manual do Linux (7) requerem que todas as funções do sistema direta ou indiretamente chamadas de uma função de sinal sejam seguras para sinais assíncronos . A página do manual do signal-safety (7) fornece uma lista de tais funções do sistema seguro do sinal async (praticamente as chamadas do sistema ), caso contrário, é um comportamento indefinido . É sugerido simplesmente definir alguma volatile sig_atomic_tvariável em um manipulador de sinal e testá-la em outro lugar.

Os manipuladores de sinal podem, em vez disso, colocar o sinal em uma fila e retornar imediatamente. O thread principal continuará "ininterrupto" até que os sinais sejam retirados da fila, como em um loop de evento . "Ininterrupto" aqui significa que as operações desse bloqueio podem retornar prematuramente e devem ser retomadas , conforme mencionado acima. Os sinais devem ser processados ​​da fila no encadeamento principal e não por pools de trabalho , pois isso reintroduz o problema de assincronicidade. No entanto, o gerenciamento de uma fila não é possível de forma segura com sinal assíncrono com apenas sig_atomic_t , já que apenas leituras e gravações únicas em tais variáveis ​​são garantidas como atômicas, e não incrementos ou (buscar e) diminuir, como seria necessário para uma fila. Assim, efetivamente, apenas um sinal por manipulador pode ser enfileirado com segurança com sig_atomic_t até que seja processado.

Relacionamento com exceções de hardware

A execução de um processo pode resultar na geração de uma exceção de hardware , por exemplo, se o processo tentar ser dividido por zero ou incorrer em uma falha de página .

Em sistemas operacionais semelhantes ao Unix, este evento altera automaticamente o contexto do processador para iniciar a execução de um manipulador de exceção do kernel . No caso de algumas exceções, como uma falha de página , o kernel tem informações suficientes para tratar totalmente o próprio evento e retomar a execução do processo.

Outras exceções, no entanto, o kernel não pode processar de forma inteligente e deve, em vez disso, adiar a operação de tratamento de exceções para o processo de falha. Esse adiamento é obtido por meio do mecanismo de sinalização, em que o kernel envia ao processo um sinal correspondente à exceção atual. Por exemplo, se um processo tentasse dividir o inteiro por zero em uma CPU x86 , uma exceção de erro de divisão seria gerada e faria com que o kernel enviasse o sinal SIGFPE para o processo.

Da mesma forma, se o processo tentasse acessar um endereço de memória fora de seu espaço de endereço virtual , o kernel notificaria o processo dessa violação por meio de um sinal SIGSEGV . O mapeamento exato entre nomes de sinais e exceções obviamente depende da CPU, uma vez que os tipos de exceção diferem entre as arquiteturas.

Sinais POSIX

A lista abaixo documenta os sinais especificados na Especificação Única do Unix . Todos os sinais são definidos como constantes de macro no <signal.h>arquivo de cabeçalho. O nome da constante macro consiste em um prefixo "SIG" seguido por um nome mnemônico para o sinal.

SIGABRT eSIGIOT
Os sinais SIGABRT e SIGIOT são enviados a um processo para instruí-lo a abortar , ou seja, encerrar. O sinal é geralmente iniciado pelo próprio processo quando ele chama a abort()função da Biblioteca Padrão C , mas pode ser enviado ao processo de fora como qualquer outro sinal.
SIGALRM ,SIGVTALRM eSIGPROF
O sinal SIGALRM, SIGVTALRM e SIGPROF é enviado a um processo quando o limite de tempo especificado em uma chamada para uma função de configuração de alarme anterior (como setitimer) expira. SIGALRM é enviado quando o tempo real ou de relógio termina. SIGVTALRM é enviado quando o tempo de CPU usado pelo processo termina. O SIGPROF é enviado quando o tempo da CPU usado pelo processo e pelo sistema em nome do processo termina.
SIGBUS
O sinal SIGBUS é enviado a um processo quando causa um erro de barramento . As condições que levam ao envio do sinal são, por exemplo, alinhamento incorreto de acesso à memória ou endereço físico inexistente.
SIGCHLD
O sinal SIGCHLD é enviado a um processo quando um processo filho termina , é interrompido ou continua após ser interrompido. Um uso comum do sinal é instruir o sistema operacional a limpar os recursos usados ​​por um processo filho após seu encerramento, sem uma chamada explícita para a waitchamada do sistema.
SIGCONT
O sinal SIGCONT instrui o sistema operacional a continuar (reiniciar) um processo anteriormente pausado pelo sinal SIGSTOP ou SIGTSTP. Um uso importante desse sinal é no controle de tarefas no shell do Unix .
SIGFPE
O sinal SIGFPE é enviado a um processo quando uma condição excepcional (mas não necessariamente errônea) é detectada no hardware de ponto flutuante ou aritmética inteira. Isso pode incluir divisão por zero , estouro negativo ou estouro de ponto flutuante, estouro inteiro, uma operação inválida ou um cálculo inexato. O comportamento pode ser diferente dependendo do hardware.
SIGHUP
O sinal SIGHUP é enviado a um processo quando seu terminal de controle é fechado. Ele foi originalmente projetado para notificar o processo de queda de linha serial (um desligamento ). Em sistemas modernos, esse sinal geralmente significa que o pseudo terminal de controle ou terminal virtual foi fechado. Muitos daemons (que não têm um terminal de controle) interpretam o recebimento desse sinal como uma solicitação para recarregar seus arquivos de configuração e liberar / reabrir seus arquivos de log em vez de sair. nohup é um comando para fazer um comando ignorar o sinal.
SIGILL
O sinal SIGILL é enviado a um processo quando ele tenta executar uma instrução ilegal , malformada, desconhecida ou privilegiada .
SIGINT
O sinal SIGINT é enviado a um processo por seu terminal de controle quando um usuário deseja interromper o processo. Isso normalmente é iniciado pressionando Ctrl+C , mas em alguns sistemas, o caractere " deletar " ou a tecla " break " podem ser usados.
SIGKILL
O sinal SIGKILL é enviado a um processo para fazer com que ele seja encerrado imediatamente ( kill ). Em contraste com SIGTERM e SIGINT, este sinal não pode ser capturado ou ignorado, e o processo de recebimento não pode realizar nenhuma limpeza ao receber este sinal. As seguintes exceções se aplicam:
  • Os processos zumbis não podem ser eliminados, pois eles já estão mortos e aguardando que seus processos pais os colham.
  • Os processos que estão no estado bloqueado não morrerão até que sejam reativados.
  • O processo init é especial: ele não recebe sinais que não deseja manipular e, portanto, pode ignorar o SIGKILL. Uma exceção a esta regra é enquanto o init é rastreado no Linux.
  • Um processo ininterrupto em hibernação pode não ser encerrado (e liberar seus recursos) mesmo quando enviado pelo SIGKILL. Este é um dos poucos casos em que um sistema UNIX pode precisar ser reinicializado para resolver um problema temporário de software.
O SIGKILL é usado como último recurso ao encerrar processos na maioria dos procedimentos de desligamento do sistema , se ele não sair voluntariamente em resposta ao SIGTERM. Para acelerar o procedimento de desligamento do computador, o Mac OS X 10.6, também conhecido como Snow Leopard , enviará SIGKILL para aplicativos que foram marcados como "limpos", resultando em tempos de desligamento mais rápidos e, provavelmente, sem efeitos nocivos. O comando killall -9tem um efeito semelhante, embora perigoso, quando executado, por exemplo, no Linux; não permite que programas salvem dados não salvos. Tem outras opções e, sem nenhuma, usa o sinal SIGTERM mais seguro.
SIGPIPE
O sinal SIGPIPE é enviado a um processo quando ele tenta gravar em um pipe sem um processo conectado à outra extremidade.
SIGPOLL
O sinal SIGPOLL é enviado quando um evento ocorre em um descritor de arquivo explicitamente observado. Usá-lo efetivamente leva à realização de solicitações de E / S assíncronas, uma vez que o kernel pesquisará o descritor no lugar do chamador. Ele fornece uma alternativa para a pesquisa ativa .
SIGRTMIN paraSIGRTMAX
Os sinais SIGRTMIN a SIGRTMAX devem ser usados ​​para fins definidos pelo usuário. Eles são sinais em tempo real .
SIGQUIT
O sinal SIGQUIT é enviado a um processo por seu terminal de controle quando o usuário solicita que o processo seja encerrado e execute um core dump .
SIGSEGV
O SIGSEGV sinal é enviado para um processo quando ele faz uma referência inválida de memória virtual, ou segmentação de culpa , isto é, quando se realiza uma seg mentação v iolation .
SIGSTOP
O sinal SIGSTOP instrui o sistema operacional a interromper um processo para reiniciá-lo posteriormente.
SIGSYS
O sinal SIGSYS é enviado a um processo quando ele passa um argumento incorreto para uma chamada de sistema . Na prática, esse tipo de sinal raramente é encontrado, pois os aplicativos dependem de bibliotecas (por exemplo, libc ) para fazer a chamada. SIGSYS pode ser recebido por aplicativos que violam as regras de segurança Linux Seccomp configuradas para restringi-los. SIGSYS também pode ser usado para emular chamadas de sistema externo, por exemplo, emular chamadas de sistema Windows no Linux.
SIGTERM
O sinal SIGTERM é enviado a um processo para solicitar seu encerramento . Ao contrário do sinal SIGKILL, ele pode ser capturado e interpretado ou ignorado pelo processo. Isso permite que o processo execute uma boa finalização, liberando recursos e salvando o estado, se apropriado. SIGINT é quase idêntico ao SIGTERM.
SIGTSTP
O SIGTSTP sinal é enviado a um processo pelo seu controlo de terminal para requerer que esta paragem ( t erminal r o p ). Normalmente é iniciado pelo usuário pressionando Ctrl+Z . Ao contrário do SIGSTOP, o processo pode registrar um manipulador de sinal para, ou ignorar, o sinal.
SIGTTIN eSIGTTOU
Os SIGTTIN e SIGTTOU sinais são enviados para um processo quando ele tenta ler em ou escrever para fora , respectivamente, do tty enquanto no fundo . Normalmente, esses sinais são recebidos apenas por processos sob controle de tarefa ; daemons não têm terminais de controle e, portanto, nunca devem receber esses sinais.
SIGTRAP
O sinal SIGTRAP é enviado a um processo quando ocorre uma exceção (ou trap ): uma condição sobre a qual um depurador solicitou ser informado - por exemplo, quando uma função específica é executada ou quando uma determinada variável muda de valor.
SIGURG
O sinal SIGURG é enviado a um processo quando um soquete tem dados urgentes ou fora de banda disponíveis para leitura.
SIGUSR1 eSIGUSR2
Os sinais SIGUSR1 e SIGUSR2 são enviados a um processo para indicar as condições definidas pelo usuário .
SIGXCPU
O sinal SIGXCPU é enviado a um processo quando ele usa a CPU por um período que excede um certo valor pré-determinado definido pelo usuário. A chegada de um sinal SIGXCPU fornece ao processo de recebimento uma chance de salvar rapidamente quaisquer resultados intermediários e sair normalmente, antes que seja encerrado pelo sistema operacional usando o sinal SIGKILL.
SIGXFSZ
O sinal SIGXFSZ é enviado a um processo quando ele aumenta um arquivo que excede o tamanho máximo permitido .
SIGWINCH
O sinal SIGWINCH é enviada a um processo em que o seu terminal de controlo altera o seu tamanho (uma vitória Dow ch ange).

Ação padrão

Um processo pode definir como lidar com os sinais POSIX de entrada . Se um processo não define um comportamento para um sinal, então o manipulador padrão para aquele sinal está sendo usado. A tabela abaixo lista algumas ações padrão para sistemas UNIX compatíveis com POSIX, como FreeBSD , OpenBSD e Linux .

Sinal
Número portátil
Ação padrão Descrição
SIGABRT 6 Terminar (despejo de núcleo) Sinal de abortar processo
SIGALRM 14 Terminar Despertador
SIGBUS N / D Terminar (despejo de núcleo) Acesso a uma parte indefinida de um objeto de memória
SIGCHLD N / D Ignorar O processo filho foi encerrado, interrompido ou continuou
SIGCONT N / D Prosseguir Continue executando, se parado
SIGFPE 8 Terminar (despejo de núcleo) Operação aritmética errônea
SIGHUP 1 Terminar Desligar
SIGILL 4 Terminar (despejo de núcleo) Instrução ilegal
SIGINT 2 Terminar Sinal de interrupção do terminal
SIGKILL 9 Terminar Matar (não pode ser capturado ou ignorado)
SIGPIPE 13 Terminar Escreva em um cachimbo sem ninguém para ler
SIGPOLL N / D Terminar Evento Pollable
SIGPROF N / D Terminar Timer de criação de perfil expirado
SIGQUIT 3 Terminar (despejo de núcleo) Sinal de saída do terminal
SIGSEGV 11 Terminar (despejo de núcleo) Referência de memória inválida
SIGSTOP N / D Pare Pare de executar (não pode ser capturado ou ignorado)
SIGSYS N / D Terminar (despejo de núcleo) Chamada de sistema ruim
SIGTERM 15 Terminar Sinal de rescisão
SIGTRAP 5 Terminar (despejo de núcleo) Traço / armadilha de ponto de interrupção
SIGTSTP N / D Pare Sinal de parada do terminal
SIGTTIN N / D Pare Tentativa de leitura do processo em segundo plano
SIGTTOU N / D Pare Tentativa de gravação de processo em segundo plano
SIGUSR1 N / D Terminar Sinal definido pelo usuário 1
SIGUSR2 N / D Terminar Sinal definido pelo usuário 2
SIGURG N / D Ignorar Dados fora de banda estão disponíveis em um soquete
SIGVTALRM N / D Terminar Temporizador virtual expirado
SIGXCPU N / D Terminar (despejo de núcleo) Limite de tempo de CPU excedido
SIGXFSZ N / D Terminar (despejo de núcleo) Limite de tamanho de arquivo excedido
SIGWINCH N / D Ignorar Tamanho da janela do terminal alterado
Número portátil:
Para a maioria dos sinais, o número do sinal correspondente é definido pela implementação. Esta coluna lista os números especificados no padrão POSIX.
Ações explicadas:
Terminar  - Término anormal do processo. O processo é encerrado com todas as consequências de _exit (), exceto que o status disponibilizado para wait () e waitpid () indica encerramento anormal pelo sinal especificado.
Terminate (core dump)  - Término anormal do processo. Além disso, podem ocorrer ações de término anormais definidas pela implementação, como a criação de um arquivo principal.
Ignorar  - ignora o sinal.
Parar  - Pare (não encerre) o processo.
Continue  - Continue o processo, se estiver parado; caso contrário, ignore o sinal.

Sinais diversos

Os seguintes sinais não são especificados na especificação POSIX . Eles são, no entanto, às vezes usados ​​em vários sistemas.

SIGEMT
O sinal SIGEMT é enviado a um processo quando ocorre um trap do emulador .
SIGINFO
O sinal SIGINFO é enviado a um processo quando uma solicitação de status ( informações ) é recebida do terminal de controle.
SIGPWR
O sinal SIGPWR é enviado para um processo quando o sistema passa por uma falha de energia .
SIGLOST
O sinal SIGLOST é enviado para um processo quando um bloqueio de arquivo é perdido .
SIGSTKFLT
O sinal SIGSTKFLT é enviado para um processo quando o coprocessador experimenta um st ac k f au lt (ou seja, estourando quando a pilha está vazia ou empurrando quando está cheia). É definido por, mas não usado no Linux, onde uma falha de pilha do coprocessador x87 irá gerar SIGFPE.
SIGUNUSADO
O sinal SIGUNUSED é enviado para um processo quando uma chamada do sistema com um número de chamada do sistema não utilizado é feita. É sinônimo de SIGSYS na maioria das arquiteturas.
SIGCLD
O sinal SIGCLD é sinônimo de SIGCHLD.

Veja também

Referências

links externos