c/c++
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;
}