Libev源码分析06:异步信号同步化--sigwait、sigwaitinfo、sigtimedwait和signalfd

一:信号简述

         信号是典型的异步事件。内核在某个信号出现时有三种处理方式:

a:忽略信号,除了SIGKILL和SIGSTOP信号不能忽略外,其他大部分信号都可以被忽略;

b:捕捉信号,也就是在信号发生时调用一个用户函数,注意不能捕捉SIGKILL和SIGSTOP;

c:执行系统默认动作,注意大多数信号的系统默认动作是终止进程。

         调用execve执行一个新的进程时,新进程的信号处理方式要么是忽略,要么是系统默认方式。如果调用进程忽略该信号,则新进程也忽略该信号,如果调用进程捕捉该信号,或者执行系统默认动作,新进程则按照默认行为处理该信号,这是因为调用进程的信号处理函数在新进程中已经无效了。

         如果是调用fork产生子进程,则子进程的信号处理方式完全继承父进程的处理方式。这是因为子进程复制了父进程的地址空间,因此父进程中的信号处理函数在子进程中同样被复制了。

        

         当信号产生以后,对信号采取了动作时,称为向进程“递送”了一个信号,在信号产生(generation)和递送(delivery)之间的时间间隔内,称信号是未决的(pending)。

         进程可以“阻塞”信号,如果为进程产生了一个阻塞的信号,而且对该信号的动作是调用信号处理函数捕捉该信号,或者是系统默认动作,则会为该进程将此信号保持为未决状态,直到a:对此信号解除了阻塞,或者b:对此信号的动作改为忽略。内核在递送一个原来被阻塞的信号给进程时(而不是产生信号时),才决定对它的处理方式,因此,进程在信号被递送之前仍可改变对该信号的动作。

         如果在进程解除某个信号的阻塞之前,该信号发生了多次,则系统可以递送该信号一次或多次。如果递送多次,则称对这些信号进行了排队。但是除非支持POSIX.1实时扩展,否则大多数UNIX并不对信号排队,也就是指递送该信号一次。

         如果有多个信号要递送给一个进程,POSIX.1并未规定这些信号的递送顺序。

         每个进程都有一个信号屏蔽字,它规定了当前要阻塞的信号集。POSIX.1使用数据类型sigset_t表示一个信号集,进程可以调用sigprocmask来检测和更改当前信号屏蔽字。

 

         对信号的处理是以进程为单位的,也就是说在多线程环境中,信号的处理是进程中所有线程共享的。但是每个线程可以有自己的信号屏蔽字,所以,单个线程可以阻塞某些信号,当某个线程修改了某个信号的处理方式后,所有线程共享这个处理方式的改变。

         进程中的信号是递送到单个线程的。如果信号与硬件故障相关,该信号就被递送到引起该事件的线程中去,而其他信号则被递送到任意一个没有阻塞该信号的线程。sigprocmask的行为在多线程中没有定义,线程必须使用相应的pthread_sigmask。

 

         除了使用信号处理函数异步的捕捉信号之外,还可以将这种异步行为变得同步,有两种方法:

         a:调用sigwaitinfo、sigtimedwait或sigwait,这些函数会阻塞调用线程,直到信号集set中的某个信号被递送为止,这些函数都会返回递送信号的信息。

         b:调用signalfd,它返回一个文件描述符,针对该描述符的read的操作将会阻塞,直到signalfd指定的信号集set中的某个信号递送给调用者为止,此时read返回一个描述该信号的结构。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值