linux信号处理响应异步事件,Linux并发(异步信号)

0818b9ca8b590ca3270a3433284dd417.png

Linux下的信号是诸多进程间通信(IPC)中唯一一种异步通信方式,这决定了信号的处理跟其他的IPC有本质差别。

拓展:

一般情况下,进程什么时候会收到信号、收到什么信号是无法事先预料的(除了某几个特殊的信号之外),信号的到来就像你家门铃的响起一样,你不知道他什么时候会响。

下图展示了内核中跟信号相关的最重要的数据组织关系:

0818b9ca8b590ca3270a3433284dd417.png

对这幅图的理解提几点重要说明:

1,每一个线程都使用一个PCB(即task_struct)来表示,因此pending(不是指针)就是一个线程单独私有的,当我们使用pthread_kill( )给一个指定的线程发送某信号时,这些信号将会被存储在这个链队列中。

2,signal是一个指向线程共享的信号挂起队列相关结构体的指针,实际上,一个线程组(即一个进程)中的所有线程中的signal指针都指向同一个结构体,当我们使用诸如kill( )来给一个进程发送某信号的时候,这些信号将会被存储在shared_pending这个线程共享的链队列中。

如果一个进程中有超过1条线程,那么这些共享的挂起信号将会被随机的某条线程响应,为了能确保让一个指定的线程响应来自进程之外的、发送给整个进程的某信号,一般的做法如下:

除了指定要响应某信号的线程外,其他线程对这些信号设置阻塞。即使用sigprocmask( )或者pthread_sigmask( )将这些需要阻塞的信号添加到信号阻塞掩码blocked当中。

3,sighand也是一个指针,因此也是进程中的所有线程共享的,他指向跟信号响应函数相关的数据结构,结构体struct sighand_struct{}中的数组action有64个元素,一一对应LINUX系统支持的64个信号(其中0号信号是测试用的,32号和33号信号保留),每一个元素是一个sigaction{}结构体,其成员就是标准C库函数sigaction( )中的第二个参数的成员,可见,该函数相当于是一个应用层给内核设置信号响应策略的窗口。

另外,在编写信号响应函数时也应非常慎重地访问进程的共享数据,必要时要加锁来保护。响应函数跟进程的其他部分函数微观上虽然是串行执行的关系,但由于信号触发点的异步特性,就使得信号响应函数的执行跟进程的其他部分函数在宏观上是并行执行关系,请看图解:

0818b9ca8b590ca3270a3433284dd417.png

可以看到,由于信号触发点可以发生在进程执行过程中的任意时刻,因此响应函数f( )事实上就是跟主进程并发的,在响应函数内部访问任何共享资源,都必须跟多线程一样,使用同步互斥机制来确保访问的安全性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值