免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4465 | 回复: 10
打印 上一主题 下一主题

apue,signal问题贴 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-07-05 13:06 |只看该作者 |倒序浏览
工作有闲,就啃啃apue

本贴是apue中关系到signal的内容方面的问题,准备按照此顺序发帖,主要方便自己查找,如果能方便其他同学解决问题,那就最好了。

问题一:

背景:见书10.13. sigpending Function 的例子程序。

实际运行此程序,结果如下,和书中一致:
$ ./a.out
   
    ^\                       generate signal once (before 5 seconds are up)
    SIGQUIT pending          after return from sleep
    caught SIGQUIT           in signal handler
    SIGQUIT unblocked        after return from sigprocmask
    ^\Quit(coredump)         generate signal again

问题:
不理解为什么“SIGQUIT unblocked”会在“caught SIGQUIT”之后打印出来?sigprocmask(SIG_SETMASK, &oldmask, NULL)重新把SIGQUIT置为UNBLOCK,那么信号处理的回调函数应该在sigprocmask调用之后执行才对,我觉得顺序应该是:

$ ./a.out
   
    ^\                       generate signal once (before 5 seconds are up)
    SIGQUIT pending          after return from sleep
   SIGQUIT unblocked        after return from sigprocmask
    caught SIGQUIT           in signal handler
     ^\Quit(coredump)         generate signal again
才好理解啊!

谢谢关注的同志!

[ 本帖最后由 NewCore 于 2007-7-5 13:35 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-07-05 13:35 |只看该作者

问题二

问题二:

背景:书apue,10.16sigsuspend Function一节的例子程序Figure 10.22. Protecting a critical region from a signal.

运行程序,输出和书中给出的结果一致:

$ ./a.out
   program start:
   in critical region: SIGINT

   ^?                               type the interrupt character
   in sig_int: SIGINT SIGUSR1
   after return from sigsuspend: SIGINT
   program exit:

问题
sigsuspend的解释"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."
我理解的是,调用sigsuspend后,当前进程的信号集“replace”为sigsuspend中参数指定的信号集。
那么,in sig_int: SIGINT SIGUSR1这里为什么同是打印出了SIGINT,和SIGUSR1呢?
sigsuspend(&waitmask);调用参数waitmask只指定了SIGUSR1信号,我理解这里应该是:in sig_int: SIGUSR1,但是和程序运行结果不符,问题在哪里呢?

论坛徽章:
0
3 [报告]
发表于 2007-07-05 15:31 |只看该作者
原帖由 NewCore 于 2007-7-5 13:06 发表于 1楼  
工作有闲,就啃啃apue

本贴是apue中关系到signal的内容方面的问题,准备按照此顺序发帖,主要方便自己查找,如果能方便其他同学解决问题,那就最好了。

问题一:

背景:见书10.13. sigpending Functio ...


在解除block之后信号会马上触发所以会先于printf("SIGQUIT unblocked\n");

执行

论坛徽章:
0
4 [报告]
发表于 2007-07-05 16:01 |只看该作者
原帖由 NewCore 于 2007-7-5 13:35 发表于 2楼  
问题二:

背景:书apue,10.16sigsuspend Function一节的例子程序Figure 10.22. Protecting a critical region from a signal.

运行程序,输出和书中给出的结果一致:

$ ./a.out
   program start:
...


POSIX guarantees that the signal being caught is always blocked while its handler is executing.

论坛徽章:
0
5 [报告]
发表于 2007-07-05 17:38 |只看该作者
原帖由 gaocheng 于 2007-7-5 16:01 发表于 4楼  


POSIX guarantees that the signal being caught is always blocked while its handler is executing.


我的问题是:   
sigemptyset(&waitmask);
sigaddset(&waitmask, SIGUSR1);
。。。。。。。。
sigsuspend(&waitmask);调用后,进程信号集只会block SIGUSER1信号,为什么在sig_int触发的时候还会有SIGINT信号?

好像你的回复不太符合题意吧。

论坛徽章:
0
6 [报告]
发表于 2007-07-05 23:31 |只看该作者

回复 #5 NewCore 的帖子

打印的是当前什么样的信号会被阻塞!
sig_int执行的的时候,SIGINT信号会被阻塞。

论坛徽章:
0
7 [报告]
发表于 2007-07-06 09:34 |只看该作者

用一个例子来说明,请看:

请看以下测试程序:


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <errno.h>

  7. /* print signal mask bits */
  8. void pr_mask(const char * _str)
  9. {
  10.     sigset_t sigset;
  11.     int errno_save;

  12.     errno_save = errno;
  13.     if(sigprocmask(0, NULL, &sigset) < 0)
  14.         printf("sigprocmask error\n");
  15.    
  16.     printf("%s", _str);
  17.     if(sigismember(&sigset, SIGINT))
  18.         printf("SIGINT ");
  19.     if(sigismember(&sigset, SIGQUIT))
  20.         printf("SIGQUIT ");
  21.     if(sigismember(&sigset, SIGUSR1))
  22.         printf("SIGUSR1 ");
  23.     if(sigismember(&sigset, SIGALRM))
  24.         printf("SIGALRM ");
  25.     if(sigismember(&sigset, SIGCHLD))
  26.         printf("SIGCHLD ");
  27.     printf("\n");
  28.     errno = errno_save;
  29. }

  30. /* signal handler */
  31. void sig_handler(int _signo)
  32. {
  33.     if(_signo == SIGCHLD)
  34.     {
  35.         printf("sig_handler <<< SIGCHLD\n");
  36.     }
  37.     else if(_signo == SIGALRM)
  38.     {
  39.         printf("sig_handler <<< SIGALRM\n");
  40.     }
  41.     else if(_signo == SIGUSR1)
  42.     {
  43.         printf("sig_handle <<< SIGUSR1\n");
  44.     }
  45.     else if(_signo == SIGQUIT)
  46.     {
  47.         printf("sig_handle <<< SIGQUIT\n");
  48.     }
  49.     else if(_signo == SIGINT)
  50.     {
  51.         printf("sig_handle <<< SIGINT\n");
  52.     }
  53.     else
  54.     {
  55.         printf("sig_handler <<< unexpect signal\n");
  56.     }
  57.     pr_mask("in sig_handle ");
  58. }

  59. /* process */
  60. int main(int argc, char * argv[])
  61. {
  62.    int pid;
  63.    int status;
  64.    int count;
  65.    sigset_t newmask, oldmask, pendmask;

  66.    signal(SIGUSR1, sig_handler);
  67.    
  68.    pr_mask("before sigprocmask: ");
  69.    
  70.    sigemptyset(&newmask);
  71.    sigemptyset(&oldmask);
  72.    sigaddset(&newmask, SIGUSR1);
  73.    sigprocmask(SIG_BLOCK, &newmask, &oldmask);

  74.    pr_mask("after sigprocmask: ");

  75.    if(0 == (pid = fork()))  /* child */
  76.    {
  77.        printf("child running, id = %d\n", getpid());
  78.        sleep(2);
  79.        kill(getppid(), SIGUSR1);
  80.        sleep(2);
  81.        printf("child exit\n");
  82.    }
  83.    else if(pid > 0)         /* parent */
  84.    {
  85.        printf("parent running, id = %d\n", getpid());
  86.        if(sigsuspend(&newmask) != -1)         /* 这里为什么不能收到SIGUSR1信号???父进程在这里死锁了... */
  87.            printf("sigsuspend error\n");
  88.        pr_mask("after return from sigsuspend ");
  89.        sleep(2);
  90.        sigprocmask(SIG_SETMASK, &oldmask, 0);
  91.    }
  92.    else                     /* error */
  93.    {
  94.        printf("fork error\n");
  95.    }
  96.    return 0;
  97. }
复制代码

[ 本帖最后由 NewCore 于 2007-7-6 09:36 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2007-07-06 10:40 |只看该作者
我知道上面代码错在哪里了。

关键就在:
sigaddset(&newmask, SIGUSR1);
sigprocmask(SIG_BLOCK, &newmask, &oldmask);

SIGUSR1已经被block,后面kill当然就收不到了,如果去掉这两句就OK了。

论坛徽章:
0
9 [报告]
发表于 2007-07-06 10:49 |只看该作者
继续测试sigsuspend,现在代码改成下面这个样子,sigsuspend还是被死锁了...


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. #include <sys/types.h>
  5. #include <unistd.h>
  6. #include <errno.h>

  7. /* print signal mask bits */
  8. void pr_mask(const char * _str)
  9. {
  10.     sigset_t sigset;
  11.     int errno_save;

  12.     errno_save = errno;
  13.     if(sigprocmask(0, NULL, &sigset) < 0)
  14.         printf("sigprocmask error\n");
  15.    
  16.     printf("%s", _str);
  17.     if(sigismember(&sigset, SIGINT))
  18.         printf("SIGINT ");
  19.     if(sigismember(&sigset, SIGQUIT))
  20.         printf("SIGQUIT ");
  21.     if(sigismember(&sigset, SIGUSR1))
  22.         printf("SIGUSR1 ");
  23.     if(sigismember(&sigset, SIGALRM))
  24.         printf("SIGALRM ");
  25.     if(sigismember(&sigset, SIGCHLD))
  26.         printf("SIGCHLD ");
  27.     printf("\n");
  28.     errno = errno_save;
  29. }

  30. /* signal handler */
  31. void sig_handler(int _signo)
  32. {
  33.     if(_signo == SIGCHLD)
  34.     {
  35.         printf("sig_handler <<< SIGCHLD\n");
  36.     }
  37.     else if(_signo == SIGALRM)
  38.     {
  39.         printf("sig_handler <<< SIGALRM\n");
  40.     }
  41.     else if(_signo == SIGUSR1)
  42.     {
  43.         printf("sig_handle <<< SIGUSR1\n");
  44.     }
  45.     else if(_signo == SIGQUIT)
  46.     {
  47.         printf("sig_handle <<< SIGQUIT\n");
  48.     }
  49.     else if(_signo == SIGINT)
  50.     {
  51.         printf("sig_handle <<< SIGINT\n");
  52.     }
  53.     else
  54.     {
  55.         printf("sig_handler <<< unexpect signal\n");
  56.     }
  57.     pr_mask("in sig_handle ");
  58. }

  59. /* process */
  60. int main(int argc, char * argv[])
  61. {
  62.    int pid;
  63.    int status;
  64.    int count;
  65.    sigset_t newmask, oldmask, pendmask;

  66. //   signal(SIGUSR1, sig_handler); -> signal(SIGALRM, sig_handler);
  67.    signal(SIGALRM, sig_handler);

  68.    pr_mask("before sigprocmask: ");
  69.    
  70.    sigemptyset(&newmask);
  71.    sigemptyset(&oldmask);
  72.    sigprocmask(0, NULL, &oldmask);  /* 保存原来的信号集 */

  73.    pr_mask("after sigprocmask: ");

  74.    if(0 == (pid = fork()))  /* child */
  75.    {
  76.        printf("child running, id = %d\n", getpid());
  77.        sleep(2);
  78.        alarm(1);   /* alarm 一下 */
  79.        sleep(2);
  80.        printf("child exit\n");
  81.    }
  82.    else if(pid > 0)         /* parent */
  83.    {
  84.        printf("parent running, id = %d\n", getpid());
  85.        if(sigsuspend(&newmask) != -1)         /* sig_handler也调用了,但是这里没有返回,父进程在这里死锁了... , why? */
  86.            printf("sigsuspend error\n");
  87.        pr_mask("after return from sigsuspend ");
  88.        sleep(2);
  89.        sigprocmask(SIG_SETMASK, &oldmask, 0);
  90.    }
  91.    else                     /* error */
  92.    {
  93.        printf("fork error\n");
  94.    }
  95.    return 0;
  96. }
复制代码

论坛徽章:
0
10 [报告]
发表于 2007-07-06 21:38 |只看该作者

估计都不想看代码,问题归纳一下

应该就是这样的:信号SIGALRM可以和SIGUSR1一样的用否?
环境:
进程A,B;A调用sigsuspend阻塞,等待B发送信号来,B在完成工作后,调用alarm向A进程发送SIGALRM信号。

问题:
结果发现,SIGALRM的信号处理函数确实已调用,但是A进程还是挂在sigsuspend处,没有返回,使用SIGUSR1是可以的,是不是SIGALRM在这里有什么不同?

请指教!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP