Conceito básico de sinal de processo e função de geração

        Os sinais são a forma mais antiga de comunicação entre processos Linux. O sinal é uma interrupção de software, que é uma simulação do mecanismo de interrupção no nível do software e é um método de comunicação assíncrona. Os sinais podem fazer com que um processo em execução seja interrompido por outro processo assíncrono em execução para lidar com um evento inesperado.

        O sinal que estudamos aqui pertence a tal interrupção. Quando pressionamos Ctrl + c no terminal, é gerada uma interrupção, que equivale a um sinal, e então esta tarefa de interrupção será processada.

As características do sinal:
1. Simples
2. Não pode transportar uma grande quantidade de informações
3. Somente quando uma determinada condição for atendida ele pode ser enviado

O sinal pode interagir diretamente entre o processo do espaço do usuário e o processo do espaço do kernel, e o processo do kernel pode usá-lo para notificar o processo do espaço do usuário sobre quais eventos do sistema ocorreram.

Um ciclo completo de sinal inclui três partes: a geração do sinal, o registro do sinal no processo, o cancelamento do sinal no processo e a execução da função de processamento do sinal.

número do sinal 

A versão inicial do Unix fornecia um mecanismo de sinal, mas não era confiável e o sinal poderia ser perdido. Mais tarde, o modelo de sinal foi alterado e um mecanismo de sinal confiável foi adicionado, mas eles eram incompatíveis entre si. POSIX.1 padronizou o mecanismo confiável rotinas de sinal

kill -l Ver números de sinal
Os sinais 1 a 31 são chamados de sinais regulares (também conhecidos como sinais comuns ou sinais padrão), 34 a 64 são chamados de sinais em tempo real e a programação do driver está relacionada ao hardware.

Para obter a lista de sinais específica, consulte a lista de sinais do Linux list_baobao8505 blog-CSDN blog_linux signal list

Quatro elementos de um sinal

1. Número 2. Nome 3. Evento 4. Ação padrão

Os números são diferentes em sistemas operacionais diferentes, mas os nomes são os mesmos

Ação é a ação padrão:

Termo: Encerrar o processo
Ign: Ignorar o processo
Core: Encerrar o processo, gerar um arquivo Core
Stop: Interromper o processo
Cont: Continuar a executar o processo

Nota: Os sinais SIGKILL e SIGSTOP não podem ser ignorados e capturados, e apenas ações padrão podem ser executadas. Não pode nem ser configurado para bloquear.

Depois que o sinal é gerado, existem dois estados 
1. Estado pendente: Não processado
2. Estado de entrega: O sinal é processado

Conjuntos de sinais de bloqueio e conjuntos de sinais pendentes

 A implementação do sinal leva a um forte atraso no sinal, mas para o usuário o tempo é muito curto e difícil de detectar

O conjunto de sinais de bloqueio
        adiciona alguns sinais ao conjunto e define a blindagem para eles. Quando o sinal x é blindado e então o sinal é recebido, o processamento do sinal será adiado (o processamento ocorre após o desbloqueio da blindagem)

O
        sinal de conjunto de sinais pendentes é gerado e o bit que descreve o sinal no conjunto de sinais pendentes é imediatamente invertido para 1, indicando que o sinal está em um estado pendente. Quando o sinal é processado, o bit correspondente volta para 0. Este momento costuma ser muito curto.

função de geração de sinal 

função matar

Usuários comuns não podem enviar sinais para usuários do sistema, mas superusuários podem enviar sinais para qualquer usuário

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

//parent process kill child process
int main(void){
    pid_t pid = -1; 
    
    pid = fork();
    if(-1 == pid){
        perror("fork");
        return 1;
    }   
    
    //child process
    if(0 == pid){
        while(1){
            printf("child process do work...\n");
            sleep(1);
        }

        //exit process
        exit(0);
    }   
    else
    {   
        //parent process

        sleep(3);
        printf("child process is time to exit...\n");
        kill(pid,15);   
        printf("parent process is time to over...\n");
    
    }   

    return 0;
}

Aqui usamos kill para encerrar o processo filho após dormir 3 segundos, então ele será encerrado após executar a saída do work 3 vezes

Envie um sinal para si mesmo usando a função raise

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>

int main(void){
    int i= 1;
    while(1){
        printf("do working %d\n",i);
    
        if(i == 4){ 
            //send a id 15 signal to myself
            raise(SIGTERM);
        }
        i++;
        sleep(1);
    }   

    return 0;
}

Resultado de saída: 

faço trabalho 1
faço trabalho 2
faço trabalho 3
faço trabalho 4
Terminado

Aqui usamos raise para enviar um sinal SIGTERM para nós mesmos. Se kill for usado, então é
kill(getpid(), SIGTERM); aqui getpid() serve para obter o ID do processo atual 

função de aborto

O padrão é enviar o sinal de terminação nº 6 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void){
    int i = 1;
    while(1){
        printf("do working %d\n",i);

        if(4 == i){ 
            abort();
        }

        i++;
        sleep(1);
    }   
    return 0;
}

Resultado de saída: 

faço trabalho 1
faço trabalho 2
faço trabalho 3
faço trabalho 4
Abortado (core dumped)

Use o alarme para definir o tempo limite 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

//测试alarm函数
int main(void){
    unsigned int ret = 0;
    
    //第一次设置闹钟 5秒钟之后就超时 发送对应信号
    ret = alarm(5);

    printf("last alarm left time is %u\n",ret);
    
    sleep(2);
    //之前没有超时的闹钟被新的设置给覆盖
    ret = alarm(3);
    printf("last alarm left time is %u\n",ret);

    printf("press any buton continue..\n");
    getchar();
    return 0;
}

O tempo restante do último alarme é 0
O tempo restante do último alarme é 3,
pressione qualquer botão para continuar.
Despertador

 O tempo não tem nada a ver com o estado do processo, não importa em que estado o processo esteja, o alarme irá cronometrar

temporizador definido

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>


int main(void){
    int ret = -1; 
    struct itimerval tmo;

    tmo.it_value.tv_sec = 3;
    tmo.it_value.tv_usec = 0;

    tmo.it_interval.tv_sec = 2;
    tmo.it_interval.tv_usec = 0;

    ret = setitimer(ITIMER_REAL, &tmo, NULL);
    if(-1 == ret){
        perror("setitimer");
        return 1;
    }   

    printf("press any button to continue...\n");
    getchar();
    return 0;
}

Acho que você gosta

Origin blog.csdn.net/weixin_43754049/article/details/126146318
Recomendado
Clasificación