Uso detalhado de pthread_sigmask

c/c++


Diretório de artigos


prefácio

Para sinais de thread, você deve esquecer signal / sigaction, eles são projetados apenas para thread único de processo único

pthread_sigmask é semelhante ao sigprocmask;

sigprocmask só pode ser usado para processo único e thread único; o processo filho do fork possui uma cópia do sinal blindado;

pthread_sigmask é usado para multithreading; o novo thread possui uma cópia do sinal blindado do thread que pthread_create;

Para o processamento de sinais de thread, é melhor usar um thread para processamento e comparação unificados, caso contrário, será muito confuso!

Em relação à segurança e reentrada de thread, existem dois conceitos: segurança de thread e reentrada

Não use sigaction/signal para processar sinais em multi-threads, caso contrário você terá que considerar reentrada, segurança de thread e outras questões, o que é muito problemático; e essas duas funções abrangem todo o processo;

Todos os códigos a seguir usam sigwait [sincronização de sinal, não chama mais a função de registro]

Você também pode usar sigwaitinfo, instruções de uso: sigwaitinfo

1. Sobre sigwait / sigwaitinfo Este método de sincronização geralmente precisa bloquear o sinal primeiro, caso contrário, verifique o sinal pendente, diferentes versões do Linux têm diferentes métodos de processamento, a situação específica ainda está no homem 2. Se você ler o código a seguir ou se
você não conhece a forma de sincronizar os sinais, pode consultar o mecanismo de mensagens do Windows;

O primeiro exemplo substitui sigprocmask:

//gcc 别忘了 -lpthread
void handler(int s){
    
    
    printf("handler :%d\n" ,s);
}
 
int main(int argc, char**argv)
{
    
    
    signal(SIGINT , handler);
    sigset_t mask;
    sigaddset(&mask , SIGINT);
    pthread_sigmask(SIG_BLOCK,&mask, NULL); //替换sigprocmask
 
    //用ctrl+\ 终止
    while(1)
        pause();
    return 0;
}

No segundo exemplo, deixe a thread filha tratar o sinal; ctrl+c aciona-o, e o sinal é enviado para o processo.
Se o código comentado abaixo for aberto, duas threads podem tratar o sinal. Qual thread deve ser usada? Geralmente , o thread principal
Por que é o thread principal? Threads no Linux são implementados por processos

#include "util.h"
#include <signal.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
 
static void * t1(void *arg){
    
    
    sigset_t * mask = (sigset_t *)arg;
    int sig = 0;
 
    while(1){
    
    
        if ( sigwait(mask,&sig)  != 0 ){
    
    
            perror(" thread sigwait :");
            continue;
        }
        printf("thread got signal : %d\n" , sig);
    }
}
 
int main(int argc, char**argv)
{
    
    
    sigset_t mask;
    sigaddset(&mask , SIGINT);
    pthread_sigmask(SIG_BLOCK,&mask, NULL);
    pthread_t t;
    pthread_create(&t,0,t1,&mask);
 
    int sig = 0;
    
    while(1) pause();
 
    /*
    while(1){
        if ( sigwait(&mask,&sig)  != 0 ){
            perror("sigwait :");
            continue;
        }
        printf(" ! main got signal : %d\n" , sig);
    }
    */
 
    return 0;
}

No terceiro exemplo, o thread principal chama o alarme, deixa o subthread lidar com isso e ctrl+c termina;
todos os sinais são bloqueados e não são mais adicionados um por um, o que é problemático

 
#include <signal.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
volatile sig_atomic_t goon = 1;
 
static void * t1(void *arg){
    
    
    sigset_t * mask = (sigset_t *)arg;
    int sig = 0;
 
    while(1){
    
    
        if ( sigwait(mask,&sig)  != 0 ){
    
    
            perror(" thread sigwait :");
            continue;
        }
        printf("thread got signal : %d\n" , sig);
        if(SIGINT == sig){
    
    
            goon = 0;
            break;
        }
    }
}
 
int main(int argc, char**argv)
{
    
    
    sigset_t mask;
    sigfillset(&mask); //屏蔽所有信号
    pthread_sigmask(SIG_BLOCK,&mask, NULL);
    pthread_t t;
    pthread_create(&t,0,t1,&mask);
 
    int sig = 0;
    while(goon){
    
    
        alarm(1);
        sleep(1);
    }
 
    pthread_join(t,0);
    puts("end");
    return 0;
}

No quarto exemplo, existem 3 threads no total: o thread principal é o mesmo acima, chamando alarme a cada segundo, um thread dedicado ao processamento de sinais e um thread de trabalho;

#include <signal.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/wait.h>
volatile sig_atomic_t goon = 1;
 
static void * worker (void *arg){
    
    
    while(goon){
    
    
        printf("worker is running , tid:%ld\n" , pthread_self());
        sleep(5);
    }
    puts("worker is done");
}
 
static void * sig_handler_thread(void *arg){
    
    
    sigset_t * mask = (sigset_t *)arg;
    int sig = 0;
    pthread_t tid = pthread_self();
    while(1){
    
    
        if ( sigwait(mask,&sig)  != 0 ){
    
    
            printf("sigwait error : %s\n" , strerror(errno));
            continue;
        }
        printf("thread :%ld got signal : %d\n" , tid,sig);
        if(SIGINT == sig){
    
    
            goon = 0;
            break;
        }
    }
}
 
int main(int argc, char**argv)
{
    
    
    sigset_t mask;
    sigfillset(&mask);
    pthread_sigmask(SIG_BLOCK,&mask, NULL);
    pthread_t tid1, tid2;
    pthread_create(&tid1,0,sig_handler_thread,&mask);
    pthread_create(&tid2,0,worker,NULL);
 
    int sig = 0;
    while(goon){
    
    
        alarm(1);
        sleep(1);
    }
 
    pthread_join(tid2,0);
    pthread_join(tid1, NULL);
    puts("end");
    return 0;
}

Acho que você gosta

Origin blog.csdn.net/zyq880625/article/details/132046697
Recomendado
Clasificación