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_t
variá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
wait
chamada 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 -9
tem 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
- Stevens, W. Richard (1992). Programação avançada no ambiente UNIX® . Reading, Massachusetts: Addison Wesley. ISBN 0-201-56317-7.
- "Especificações básicas do grupo aberto, edição 7, edição de 2013" . O Grupo Aberto . Retirado em 19 de junho de 2015 .
links externos
- Tabela de Sinais Unix, Ali Alanjawi, Universidade de Pittsburgh
- Man7.org Signal Man Page
- Introdução à programação de sinais Unix Introdução à programação de sinais Unix na máquina Wayback (arquivado em 26 de setembro de 2013)
- Outra introdução à programação de sinais do Unix (postagem no blog, 2009)
- UNIX e sinais POSIX confiáveis de Baris Simsek
- Manipuladores de sinais por Henning Brauer