Tratamento de Sinais
Luiz Affonso Guedes
1
Ivanovitch Silva
1
[email protected] [email protected]
1
Universidade Federal do Rio Grande do Norte
Sum ´ario
1
Conceito e tratamento de Sinais
Introduc¸ ˜ao
Exemplos de sinais
Func¸ ˜oes Signal Handler
2
Func¸ ˜ao signal
Exemplo 01
Exemplo 02
3
Func¸ ˜ao kill
Exemplo 03
Exemplo 04
4
Func¸ ˜ao alarm
Exemplo 05
5
Desafio
Sum ´ario
1
Conceito e tratamento de Sinais
Introduc¸ ˜ao
Exemplos de sinais
Func¸ ˜oes Signal Handler
2
Func¸ ˜ao signal
Exemplo 01
Exemplo 02
3
Func¸ ˜ao kill
Exemplo 03
Exemplo 04
4
Func¸ ˜ao alarm
Exemplo 05
5
Desafio
Introduc¸ ˜ao
Sinais em Linux e Unix
Sinais s ˜ao enviados para os processos em decorr ˆencia de
algum evento (ass´ıncronos).
S ˜ao tratados como sendo interrupc¸ ˜oes de software.
Cada sinal apresenta um n ´umero de identificac¸ ˜ao. Os
nomes dos sinais s ˜ao definidos em
sys/signal.h
.
Padronizac¸ ˜ao do nome:
SIGXXX. Onde XXX ´e o
mnem ˆonico relativo ao sinal.
Ex.: SIGKILL.
Introduc¸ ˜ao
Enviando um sinal
Quando o kernel envia um sinal a um processo, o
processo pode indicar que se execute uma das ac¸ ˜oes
seguintes:
Ignorar o sinal
- o sinal ser ´a descartado pelo kernel. O
processo continua seu processamento.
Existem sinais
que n ˜ao podem ser ignorados pelo processo.
Processar o sinal
- o processo configura uma func¸ ˜ao,
signal handler, para o tratamento do sinal.
Aplicar ac¸ ˜ao default
- o pr ´oprio kernel ir ´a determinar a
ac¸ ˜ao a ser aplicada.
Exemplos de sinais
Alguns exemplos de sinais
SIGKILL
- este sinal n ˜ao pode ser ignorado nem pode
configurar uma func¸ ˜ao (signal handler ). A ac¸ ˜ao default
dele ´e terminar o processo.
SIGTERM
- usado para implementar a morte programada
de um processo. ´
E o sinal defalut do comando kill.
SIGSTOP
- faz o processo ficar parado no sistema. N ˜ao
pode ser ignorado nem pode configurar uma func¸ ˜ao
(signal handler ).
SIGCONT
- indica que o processo mude seu status de
parado para executando.
SIGINT
- interrupc¸ ˜ao de terminal, geralmente um ctrl-c.
Func¸ ˜oes Signal Handler
Func¸ ˜oes para tratamento de sinais
SIG DFL
- handling padr ˜ao. O sinal ´e manipulado com o
procedimento padr ˜ao para um determinado sinal.
Sum ´ario
1
Conceito e tratamento de Sinais
Introduc¸ ˜ao
Exemplos de sinais
Func¸ ˜oes Signal Handler
2
Func¸ ˜ao signal
Exemplo 01
Exemplo 02
3
Func¸ ˜ao kill
Exemplo 03
Exemplo 04
4
Func¸ ˜ao alarm
Exemplo 05
5
Desafio
Func¸ ˜ao signal
Sintaxe:
void
(*signal
(
int
sig, void (*func) (
int
)
) ) (int)
Par ˆametros:
int
sig - o nome do sinal sobre o qual ser ´a efetuado o
processamento.
void (*func) (
int
) - func¸ ˜ao signal handler que ser ´a executada na
ocorr ˆencia do sinal.
Retorno:
Enderec¸o de
func
Exemplo 01
Capturando uma interrupc¸ ˜ao do terminal
Download
1 //Compilar: g++ -o nomeExecutavel nomeDoArquivo.cpp
2 //Executar: ./nomeExecutavel
3 #include<s i g n a l . h>// definicao dos sinais
4 #include<s t d i o . h> 5 #include<u n i s t d . h>
6 //Funcao signal handler responsavel por tratar o sinal
7 voidf u n c a o S i g n a l H a n d l e r (int s i g ) 8 {
9 printf( ” Nao a d i a n t a usar o s i n a l : %d \n ” , s i g ) ; 10 printf( ” Apenas t e r m i n o com um k i l l −9 %d\n ” ,getpid( ) ) ; 11 }
12 intmain ( ) {
13 //Instalar a func¸˜ao para tratar o sinal de interrupcao de terminal
14 s i g n a l ( SIGINT , f u n c a o S i g n a l H a n d l e r ) ; 15
16 while( 1 ) {
17 printf( ” Processo : %d v a i d o r m i r por 1 segundo . \ n ” ,getpid( ) ) ; 18 sleep( 1 ) ;
19 } 20 }
Exemplo 02
Capturando uma interrupc¸ ˜ao do terminal
Download
1 //Compilar: g++ -o nomeExecutavel nomeDoArquivo.cpp
2 //Executar: ./nomeExecutavel
3 . . .
4 //Funcao signal handler responsavel por tratar o sinal
5 voidf u n c a o S i g n a l H a n d l e r (int s i g ) 6 {
7 printf( ” Nao a d i a n t a usar o s i n a l : %d \n ” , s i g ) ; 8 printf( ” Apenas t e r m i n o com um k i l l −9 %d\n ” ,getpid( ) ) ; 9 // Instalar a funcao default para SIGINT, nesse caso um exit
10 s i g n a l ( SIGINT , SIG DFL ) ; 11 }
12
13 intmain ( ) {
14 //Instalar a func¸˜ao para tratar o sinal de interrupcao de terminal
15 s i g n a l ( SIGINT , f u n c a o S i g n a l H a n d l e r ) ; 16
17 while( 1 ) {
18 printf( ” Processo : %d v a i d o r m i r por 1 segundo . \ n ” ,getpid( ) ) ; 19 sleep( 1 ) ;
20 } 21 }
Sum ´ario
1
Conceito e tratamento de Sinais
Introduc¸ ˜ao
Exemplos de sinais
Func¸ ˜oes Signal Handler
2
Func¸ ˜ao signal
Exemplo 01
Exemplo 02
3
Func¸ ˜ao kill
Exemplo 03
Exemplo 04
4
Func¸ ˜ao alarm
Exemplo 05
5
Desafio
Descric¸ ˜ao
A func¸ ˜ao kill serve para enviar um sinal para um
determinado processo ou para um grupo de processos.
O sinal s ´o ser ´a entregue no processo destino caso exista
permiss ˜ao.
Um processo com permiss ˜ao de
root pode enviar
qualquer sinal para qualquer processo.
Um processo us ´uario pode enviar sinais somente para
processos pertencentes ao mesmo us ´uario.
Func¸ ˜ao kill
Sintaxe:
int
kill
(
pid t pid,
int
sig)
Par ˆametros:
pid t pid - identificador do processo ao qual pretende-se
comunicar
int
sig - o nome do sinal sobre o qual ser ´a efetuado o
processamento.
Observac¸ ˜ao: se pid for
>0: o sinal ´e enviado para o processo identificado no
par ˆametro
=
0: o sinal ´e enviado para todos os processos do mesmo
grupo que o processo identificado no par ˆametro
< −1: o sinal ´e enviado para todos os processos que tenham o
valor do grupo igual ao valor absoluto do par ˆametro pid
Exemplo 03
Finalizar um processo filho atrav ´es da func¸ ˜ao kill
Download
1 . . . 2 i d P r o c e s s o = f o r k ( ) ; 3 switch( i d P r o c e s s o ){
4 case−1: // erro na abertura do processo filho
5 exit( 1 ) ;
6 case 0 : // retorno de fork para processo filho
7 while( 1 ) {
8 printf( ” Sou o processo f i l h o ID : %d , p a i ID : %d\n ” , getpid( ) , getppid( ) ) ; 9 sleep( 1 ) ;
10 } 11 break;
12 default: // processo pai
13 int c o n t = 0 ; 14 while( 1 ) {
15 printf( ” Sou o processo p a i com ID : %d , p a i ID : %d , f i l h o ID : %d\n ” , 16 getpid( ) , getppid( ) , i d P r o c e s s o ) ;
17 sleep( 1 ) ;
18 if ( c o n t ++==4)kill( idProcesso , SIGKILL ) ; //finalizar o processo filho
19 } 20 break; 21 } 22 exit ( 0 ) ; 23 }
Exemplo 04
Enviar um sinal para o processo filho
Download
1 //Funcao signal handler responsavel por tratar o sinal
2 voidf u n c a o S i g n a l H a n d l e r (int s i g ) 3 {
4 printf( ” Sou o processo f i l h o : %d , RECEBI UMA MENSAGEM DO MEU PAI : %d\n ” , 5 getpid( ) ,getppid( ) ) ;
6 exit( 1 ) ; 7 }
8 intmain ( ) { 9 . . .
10 //Instalar a func¸˜ao para tratar o sinal do usuario
11 s i g n a l ( SIGUSR1 , f u n c a o S i g n a l H a n d l e r ) ; 12 // Criando o processo
13 i d P r o c e s s o = f o r k ( ) ; 14 switch( i d P r o c e s s o ){ 15 . . .
16 default: // processo pai
17 int c o n t = 0 ; 18 while( 1 ) {
19 printf( ” Sou o processo p a i com ID : %d , p a i ID : %d , f i l h o ID : %d\n ” , getpid( ) , 20 getppid( ) , i d P r o c e s s o ) ;
21 sleep( 1 ) ;
22 if ( c o n t ++==4)kill( idProcesso , SIGUSR1 ) ; //finalizar o processo filho
23 } 24 . . .
Sum ´ario
1
Conceito e tratamento de Sinais
Introduc¸ ˜ao
Exemplos de sinais
Func¸ ˜oes Signal Handler
2
Func¸ ˜ao signal
Exemplo 01
Exemplo 02
3
Func¸ ˜ao kill
Exemplo 03
Exemplo 04
4
Func¸ ˜ao alarm
Exemplo 05
Func¸ ˜ao alarm
Sintaxe:
unsigned int
alarm
(
unsigned int sec)
Par ˆametro:
unsigned int sec: a func¸ ˜ao configura um temporizador em
tempo-real para expirar em
sec segundos. Para cancelar
algum alarme existente ´e preciso apenas chamar a func¸ ˜ao com
o par ˆametro
sec igual a
zero
.
Retorno:
A func¸ ˜ao retorna o tempo, em segundos, restante para que o
alarme anterior expire. Se nenhum alarme tiver sido
Exemplo 05
Manipulando alarmes
Download
1 //Funcao signal handler responsavel por tratar o alarme
2 voidd e t e c t a r A l a r m e (int s i g ){
3 printf( ”O s i n a l %d f o i r e c e b i d o : SIGALRM\n ” , s i g ) ; 4 printf( ” Vontando para o programa p r i n c i p a l \n ” ) ; 5 kill(getpid( ) , SIGKILL ) ;
6 } 7 main ( ) {
8 // Instalar o tratamento do alarme
9 s i g n a l ( SIGALRM , d e t e c t a r A l a r m e ) ;
10 unsigned int t e m p o R e s t a n t e A l a r m e A n t e r i o r ; 11 t e m p o R e s t a n t e A l a r m e A n t e r i o r = alarm( 5 ) ;
12 printf( ” Tempo r e s t a n t e do alarme a n t e r i o r : %d\n ” , t e m p o R e s t a n t e A l a r m e A n t e r i o r ) ; 13 sleep( 2 ) ;
14 // Ao chamar alarm() antes do alarme anterior expirar, faz com que
15 // o alarme anterior seja perdido
16 t e m p o R e s t a n t e A l a r m e A n t e r i o r = alarm( 5 ) ;
17 printf( ” Tempo r e s t a n t e do alarme a n t e r i o r : %d\n ” , t e m p o R e s t a n t e A l a r m e A n t e r i o r ) ; 18 sleep( 1 ) ;
19 t e m p o R e s t a n t e A l a r m e A n t e r i o r = alarm( 5 ) ;
20 printf( ” Tempo r e s t a n t e do alarme a n t e r i o r : %d\n ” , t e m p o R e s t a n t e A l a r m e A n t e r i o r ) ; 21 while(true){
22 sleep( 1 ) ;
23 printf( ” Esperar s e r f i n a l i z a d o \n ” ) ; };