Linux的进程间通信(信号)

Linux的进程间通信(信号)

信号的本质

软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。信号是进程间通信机制中唯一的异步通信机制,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。异步意味着我们不需要创建单独的线程来接收信号, 信号在软件层次上是对中断机制的一种模拟。

进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。信号机制除了基本通知功能外,还可以传递附加信息(基于POSIX标准)。

 

进程对信号的处理

收到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:

第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理, 进程通过系统调用signal来指定进程对某个信号的处理行为。

第二种方法是,忽略某个信号,对该信号不做任何处理,就像未发生过一样。

第三种方法是,执行操作系统的缺省动作。

 

当进程执行一个信号处理程序的函数时,通常屏蔽相应的信号,即自动阻塞这个信号,直到处理程序结束。因此,所处理的信号的另一次出现,并不能中断信号处理程序,所以信号处理函数不必是可以重入的。但是默认情况下当前信号执行的时候, 并不会屏蔽其它的信号, 如果需要屏蔽其它信号, 可以调用sigaction()函数来设置需要block的信号.

 

内核中关于信号处理的关键流程

 

内核发送信号的流程

Sys_kill()->do_tkill()->do_send_specific()->do_send_sig_info()->send_signal()->complete_signal()->signal_wake_up()

 

signal_wake_up()首先为进程设置TIF_SIGPENDING标志,说明该进程有延迟的信号要等待处理。然后再调用wake_up_state()唤醒目标进程,如果目标进程在其他的CPU上运行,wake_up_state()将返回0,此时调用kick_process()向该CPU发送一个处理器间中断, 加速触发目标进程对信号的处理.

 

进程处理信号的流程

当进程被调度时,会调用do_notify_resume()来处理信号队列中的信号。_TIF_SIGPENDING标志是在signal_wake_up()函数中设置的,检查该标志后,接下来就调用do_signal()函数来处理信号. Do_signal()中会通过user_mode来判断当前进程是否将要回到用户态, 如果是由调用handle_signal()来处理信号. 信号处理程序执行完毕之后,进程会主动调用sys_sigreturn ()系统调用再次回到内核, 然后恢复进程的用户态堆栈, 进程便可以返回用户态继续执行了.

 

总结

信号是异步的.

每个线程都可能接收到信号, 取决于它的掩码, 每个线程都有自己的掩码.

信号在进程上下文中被处理, 内核会在系统调用返回的时候, 处理pending的信号. 如果用户定义了信号的关联函数,内核则会强暴进程的用户态堆栈(由于信号处理函数在用户空间), 让它自觉的处理信号处理函数.

信号在软件层次上是对中断机制的一种模拟. 但是由于有用户态回调函数的原因, 信号的处理流程比中断更加复杂, 因为有更多的内核-用户态切换, 还要准备和恢复栈帧.

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值