设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

linux c ---sigsuspend 执行过程分析

2012-4-12 11:15| 发布者: 红黑魂| 查看: 2162| 评论: 0|来自: csdn博客

摘要: 用于在接受到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。1/*Thesigsuspend()functionreplacesthecurrentsignalmaskofthecallingthreadwiththesetofsignalspointed2tobysigmask ...

用于在接受到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。


/*The sigsuspend() function replaces the current signal mask of the calling thread with the set of signals pointed  

   to by sigmask and then suspends the thread until delivery of a signal whose action is either to execute a signal-catching  

  function or to terminate the process. This will not cause any other signals that may have been pending on the process to  

  become pending on the thread. 

If the action is to terminate the process then sigsuspend() will never return. If the action is to execute a signal-catching  

  function, thensigsuspend() will return after the signal-catching function returns, with the signal mask restored to the set  

  that existed prior to thesigsuspend() call. 

It is not possible to block signals that cannot be ignored. This is enforced by the system without causing an error to be indicated.*/  



  也就是说,sigsuspend后,进程就挂在那里,等待着开放的信号的唤醒。系统在接受到信号后,马上就把现在的信号集还原为原来的,然后调用处理函数。

Stevens在《Unix环境高级编程》一书中是如是回答的“If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend.”,由于sigsuspend是原子操作,所以这句给人的感觉就是先调用signal handler先返回,然后sigsuspend再返回。


int main(void) {  

10    sigset_t   newmask, oldmask, zeromask;  

11   

12    if (signal(SIGINT, sig_int) == SIG_ERR)  

13       err_sys("signal(SIGINT) error");  

14   

15    sigemptyset(&zeromask);  

16   

17    sigemptyset(&newmask);  

18    sigaddset(&newmask, SIGINT);  

19    /* block SIGINT and save current signal mask */  

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

21       err_sys("SIG_BLOCK error");  

22   

23    /* critical region of code */  

24    pr_mask("in critical region: ");  

25   

26    /* allow all signals and pause */  

27    if (sigsuspend(&zeromask) != -1)  

28       err_sys("sigsuspend error");  

29    pr_mask("after return from sigsuspend: ");  

30   

31    /* reset signal mask which unblocks SIGINT */  

32    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)  

33       err_sys("SIG_SETMASK error");  

34   

35    /* and continue processing ... */  

36    exit(0);  

37 }  

38   

39 static void sig_int(int signo) {  

40    pr_mask("\nin sig_int: ");  

41    return;  

42 }  


 
结果:


43 $a.out  

44 in critical region: SIGINT  

45 ^C  

46 in sig_int: SIGINT  

47 after return from sigsuspend: SIGINT  

如果按照sig_handler先返回,那么SIGINT是不该被打印出来的,因为那时屏蔽字还没有恢复,所有信号都是不阻塞的。那么是Stevens说错了么?当然没有,只是Stevens没有说请在sigsuspend的原子操作中到底做了什么?
sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,恢复原先mask;
(3) 调用该进程设置的信号处理函数;
(4) 待信号处理函数返回后,sigsuspend返回。
大致就是上面这个过程,噢,原来signal handler是原子操作的一部分,而且是在恢复屏蔽字后执行的,所以上面的例子是没有问题的,Stevens说的也没错。由于Linux和Unix的千丝万缕的联系,所以在两个平台上绝大部分的系统调用的语义是一致的。上面的sigsuspend的原子操作也是从《深入理解Linux内核》一书中揣度出来的。书中的描述如下:


48 /*The sigsuspend( ) system call puts the process in the TASK_INTERRUPTIBLE state, after having blocked the standard signals specified 

49  by a bit mask array to which the mask parameter points. The process will wake up only when a nonignored, nonblocked signal is sent  

50 


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部