linux的屏蔽信号,Linux--信号阻塞与屏蔽

1. sigprocmask函数提供屏蔽和解除屏蔽信号的功能。

从而实现关键代码的运行不被打断。

函数声明如下:

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

其中参数 how可设置的参数为:SIG_BLOCK, SIG_UNBLOCK,SIG_SETMASK

SIG_BLOCK:

按照参数 set 提供的屏蔽字,屏蔽信号。并将原信号屏蔽保存到oldset中。

SIG_UNBLOCK:

按照参数 set 提供的屏蔽字进行信号的解除屏蔽。针对Set中的信号进行解屏。

SIG_SETMASK:

按照参数 set 提供的信号设置重新设置系统信号设置。

2. 信号屏蔽与解屏常见实现

方法一: SIG_BLOCK, SIG_UNBLOCK成对实现

优点oldset可以不管。

方法二:

SIG_BLOCK设置屏蔽,保存原有信号设置。

SIG_SETMASK重新恢复原有设置。

3. 屏蔽过程中接受到的信号如何处理

在信号屏蔽过程中,出现的所有被屏蔽的信号,不管发生多少次,在信号解除屏蔽后,系统会执行一次被屏蔽信号上的操作。

#include

#include

#include

int flag_sigusr1 = 0;

int flag_sigusr2 = 0;

void sig_usr1(int signo)

{

fprintf(stdout, "caught SIGUSR1\n");

flag_sigusr1 = 1;

return;

}

void sig_usr2(int signo)

{

fprintf(stdout, "caught SIGUSR2\n");

flag_sigusr2 = 1;

return;

}

int main(void){

sigset_t newmask, oldmask;

signal(SIGUSR1, sig_usr1);

signal(SIGUSR2, sig_usr2);

fprintf(stdout, "catch sigusr1 can break\n");

while(1)

{

if(flag_sigusr1)

{

fprintf(stdout, "break\n");

break;

}

sleep(5);

}

fprintf(stdout, "first while was broken\n");

//重新设置为0

flag_sigusr1 = 0;

flag_sigusr2 = 0;

// block SIGUSR1

sigemptyset(&newmask);

sigaddset(&newmask, SIGUSR1);

if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)

{

perror("sigprocmask error");

}

fprintf(stdout, "only catch sigusr2 can break, because sigusr1 has been blocked\n");

while(1)

{

if(flag_sigusr1 || flag_sigusr2)

{

fprintf(stdout, "break\n");

break;

}

sleep(5);

}

fprintf(stdout, "second while was broken\n");

fprintf(stdout, "after second while was broken, flag_sigusr1=%d, flag_sigusr2=%d\n", flag_sigusr1, flag_sigusr2);

return 0;

}

多线程情况下每个线程共用信号处理函数,但是每个线程可以选择自己是否block某个信号。

再看一个多线程的例子:子线程的功能同上,主线程接收到hup信号会向子线程发送usr2信号。

#include

#include

#include

#include

int flag_sigusr1 = 0;

int flag_sigusr2 = 0;

int flag_sighup = 0;

void sig_usr1(int signo)

{

fprintf(stdout, "sig|caught SIGUSR1\n");

flag_sigusr1 = 1;

return;

}

void sig_usr2(int signo)

{

fprintf(stdout, "sig|caught SIGUSR2\n");

flag_sigusr2 = 1;

return;

}

void sig_hup(int signo)

{

fprintf(stdout, "sig|caught SIGHUP\n");

flag_sighup = 1;

return;

}

void *thread_control_signal(void *arg)

{

sigset_t newmask, oldmask;

sigemptyset(&newmask);

//thread block sighup

sigemptyset(&newmask);

sigaddset(&newmask, SIGHUP);

if(pthread_sigmask(SIG_BLOCK, &newmask, &oldmask) < 0)

{

perror("sigprocmask error");

}

fprintf(stdout, "thread|first while. catch sigusr1 or sigusr2 can break\n");

while(1)

{

if(flag_sigusr1 || flag_sigusr2)

{

fprintf(stdout, "thread|break\n");

break;

}

sleep(5);

}

flag_sigusr1 = 0;

//thread block SIGUSR1

sigaddset(&newmask, SIGUSR1);

if(pthread_sigmask(SIG_BLOCK, &newmask, &oldmask) < 0)

{

perror("sigprocmask error");

}

fprintf(stdout, "thread|first while. catch sigusr2 can break\n");

while(1)

{

if(flag_sigusr1 || flag_sigusr2)

{

fprintf(stdout, "break\n");

break;

}

sleep(10);

}

fprintf(stdout, "thread|thread exit\n");

return (void *)0;

}

int main()

{

sigset_t newmask;

pthread_t tid;

int signo;

//signal action

signal(SIGUSR1, sig_usr1);

signal(SIGUSR2, sig_usr2);

signal(SIGHUP , sig_hup);

if(pthread_create(&tid, NULL, thread_control_signal, NULL) < 0)

{

perror("create pthread failed");

return -1;

}

//main thread block sigusr1

sigemptyset(&newmask);

sigaddset(&newmask, SIGUSR1);

if(pthread_sigmask(SIG_BLOCK, &newmask, NULL) < 0)

{

perror("sigprocmask error");

}

//main thread wait sighup

sigemptyset(&newmask);

sigaddset(&newmask, SIGHUP);

if(sigwait(&newmask, &signo) < 0)

{

perror("sigwait failed");

return -1;

}

fprintf(stdout, "main|get SIGHUP\n");

pthread_kill(tid, SIGUSR2);

pthread_kill(tid, SIGUSR2);

pthread_join(tid, NULL);

fprintf(stdout, "main|exit\n");

return 0;

}

kill函数向进程发送信号,pthread_kill用于向线程发送信号。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值