设为首页收藏本站

LUPA开源社区

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

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

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

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

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


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

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

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

4   become pending on the thread. 

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

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

7   that existed prior to thesigsuspend() call. 

8 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再返回。


9 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号 )   

返回顶部