免费注册 查看新帖 |

Chinaunix

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

求教:信号被挂起,sigwait()函数的作用 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-02-24 16:14 |只看该作者 |倒序浏览
大家好.
看书看到sigwait()函数的解释

int sigwait(const sigset_t *restrict sigmask, int* restrict signo);

sigwait函数一直阻塞直到*sigmask指定的任何一个信号被挂起为止,然后从挂起信号集中删除那个信号,并解除对它的阻塞。当sigwait返回时,从挂起信号集中删除的信号的个数被存储在signo指定的那个位置中。


在这里,信号被挂起是什么意思呢?被挂起不是被阻塞吧?
其中,书上对信号有这么一段描述:

信号是向进程发送的软件通知,通知进程有事件发生。引发信号的事件发生时,信号就被生成了。进程根据信号采取行动时,信号就被传递了。信号的寿命就是信号的生成和传递之间的时间间隔。已经生成但还未被传递的信号被称为挂起的信号。在信号生成和信号传递之间可能会有相当长的时间。



在这里,我有有点迷糊了,“sigwait函数一直阻塞直到*sigmask指定的任何一个信号被挂起为止”
在什么情况下,信号会被挂起呢?

"已经生成但还未被传递的信号被称为挂起的信号。"
这里是不是说:信号被生成到信号被传递之间的时间差就是信号被挂起这个阶段?
那也就是说:任何信号都会被挂起一段时间才会被传递?信号被阻塞这个动作,也是信号被传递了?

不知道我的理解是否正确,大家能不能举例说明一下?
谢谢!

论坛徽章:
0
2 [报告]
发表于 2008-02-24 18:14 |只看该作者
原帖由 new_learner 于 2008-2-24 16:14 发表
1.这里是不是说:信号被生成到信号被传递之间的时间差就是信号被挂起这个阶段?
2.那也就是说:任何信号都会被挂起一段时间才会被传递?信号被阻塞这个动作,也是信号被传递了?

个人看法:
1。对
2。那也就是说:任何信号都会被挂起一段时间才会被传递?信号被阻塞这个动作(即传递),也就是信号不能被传递

挂起就是未决pending(未处理的)

信号类似于处理事务
1。有事情发生了(信号产生)
2。该事情通知了有关部门,他们已登记在一个未处理事件的本子上(信号传递给目标进程,目标进程登记该信号到本进程的task_struct结构)
3。有关部门定期检查未处理事件的本子,发现有事情没处理时,就注销该事件(目标进程会检测是否有信号等待处理,如果有未决信号等待处理且该信号没有被进程阻塞,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉)
4。最后有关部门去实施事件的处理。(进程注销信号后,立即执行相应的信号处理函数,执行完毕后,信号的本次发送对进程的影响彻底结束。)

int sigwait(const sigset_t *restrict sigmask, int* restrict signo);

sigwait函数一直阻塞直到*sigmask指定的任何一个信号被挂起为止,然后从挂起信号集中删除那个信号,并解除对它的阻塞。当sigwait返回时,从挂起信号集中删除的信号的个数被存储在signo指定的那个位置中。
这里的sigwait是阻塞本进程,去等待指定的信号。等到了就会解除阻塞。

论坛徽章:
0
3 [报告]
发表于 2008-02-24 18:26 |只看该作者
搞错了sigwait是线程函数

论坛徽章:
0
4 [报告]
发表于 2008-02-24 23:33 |只看该作者
非常感谢LS的兄弟
我似乎有点明白了

sigwait就是等待发往本进程的指定信号SIGXXX,一旦本进程接受到了指定信号SIGXXX(即目标进程登记该信号到本进程的task_struct结构),sigwait就返回,这时本进程就当该指定信号SIGXXX没有被接受到,继续执行下面的代码。

另外,在你提到的
“3。有关部门定期检查未处理事件的本子,发现有事情没处理时,就注销该事件(目标进程会检测是否有信号等待处理,如果有未决信号等待处理且该信号没有被进程阻塞,则在运行相应的信号处理函数前,进程会把信号在未决信号链中占有的结构卸掉)
”中
sigwait()函数中的第二个参数int* restrict signo,是不是就是说:在每两次“定期检查”中,如果sigmask中有指定的信号被挂起,那么signo就返回被挂起的信号数量?

不知道我的理解是否正确?谢谢!~

论坛徽章:
0
5 [报告]
发表于 2008-03-04 23:35 |只看该作者
又看了下书上的代码,好像又糊涂了。。。
书上这段程序:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
&nbsp;&nbsp;&nbsp;int signalcount = 0;
&nbsp;&nbsp;&nbsp;int signo;
&nbsp;&nbsp;&nbsp;int signum = SIGUSR1;
&nbsp;&nbsp;&nbsp;sigset_t sigset;

&nbsp;&nbsp;&nbsp;if ((sigemptyset(&sigset) == -1) ||
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sigaddset(&sigset, signum) == -1) ||
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(sigprocmask(SIG_BLOCK, &sigset, NULL) == -1))
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("Failed to block signals before sigwait");
&nbsp;&nbsp;&nbsp;fprintf(stderr, "This process has ID %ld\n", (long)getpid());
&nbsp;&nbsp;&nbsp;for ( ; ; ) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (sigwait(&sigset, &signo) == -1) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("Failed to wait using sigwait");
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;signalcount++;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf(stderr, "Number of signals so far: %d\n", signalcount);
&nbsp;&nbsp;&nbsp;}
}


是为了统计该进程收到了多少个SIGUSR1信号。

那为什么在sigwait之前,要把调用sigprocmask把SIGUSR1信号阻塞呢?
在sigwait之前已经把SIGUSR1信号阻塞了,那sigwait是怎么感知到进程收到了SIGUSR1信号的呢?

论坛徽章:
0
6 [报告]
发表于 2008-05-28 17:05 |只看该作者
原帖由 hyvgs 于 2008-5-28 16:42 发表
试试用中国人能理解的方式解释一下

sigprocmask中的SIG_BLOCK是让信号挂起,不去激活信号处理函数;SIG_UNBLOCK反之
sigwait是用来发现有信号发生,转入到sigwait调用线程。(sigwait的实现在不同的unix变体 ...


让你越说越迷糊,我认为sigwait跟sigsuspend类似,都是阻塞等待sigprocmask屏蔽的信号的到来,然后执行其信号handler,sigsuspend用于进程,sigwait用于线程,我是这么理解的,并没什么证据。

论坛徽章:
0
7 [报告]
发表于 2008-05-29 08:51 |只看该作者
原帖由 dxbh 于 2008-5-28 17:05 发表


让你越说越迷糊,我认为sigwait跟sigsuspend类似,都是阻塞等待sigprocmask屏蔽的信号的到来,然后执行其信号handler,sigsuspend用于进程,sigwait用于线程,我是这么理解的,并没什么证据。


可能sigsuspend和sigprocmask来进行比较更合适。
sigsuspend是用来临时修改信号掩码。sigsuspend返回后,只是表明有信号发生,且被信号handler处理了。
调用sigsuspend返回后不会获得信号的控制权,这点很重要。
我觉得可以这样说,sigsuspend是一个阻塞的临时修改信号掩码的sigprocmask。

调用sigsuspend临时修改信号掩码,使用handler来处理信号。
调用sigwait返回后获得信号控制权,可以不使用handler来处理信号。

有种说法是sigsuspend不是线程安全,没有验证过。

[ 本帖最后由 hyvgs 于 2008-5-29 09:19 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2008-05-29 09:42 |只看该作者
原帖由 hyvgs 于 2008-5-29 08:51 发表


可能sigsuspend和sigprocmask来进行比较更合适。
sigsuspend是用来临时修改信号掩码。sigsuspend返回后,只是表明有信号发生,且被信号handler处理了。
调用sigsuspend返回后不会获得信号的控制权,这点很 ...


信号控制权,什么叫信号控制权?

论坛徽章:
0
9 [报告]
发表于 2008-12-11 00:46 |只看该作者

回复lz

1,sigwait函数使得进程挂起,并对于参数1中所指向的sigset_t型数据里的signal进行监测。
2,它监测的是sigset_t型数据里的signal信号被阻塞了的信息。
3,如果监测到信息则使得它解除阻塞。也就是使得这个信号从叫做“挂起信号集”的数据结构中清除。使得该信号可以被相应的处理程序处理。
4,只有在接受到了sigset_t型数据里的signal信号后才会返回调用进程
注意:一:为什么还设一个参数指向一个个数呢?因为在“挂起信号集”里挂的可以是很多个同样的信号。都被挂起。。比如你按了2次ctrl-z则在“挂起信号集”里记录了2次SIGINT信号,如果sigset_t型数据里的signal有这个信号则sigwait函数解除对它的阻塞并且把2个SIGINT信号都删除把2传给2号参数。。
二:2就是为什么要提前阻塞要监视的信号的原因

论坛徽章:
0
10 [报告]
发表于 2008-12-11 00:52 |只看该作者

补充

挂起信号集 , 阻塞信号集是不一样的概念
挂起信号集是存在于TASK_STRUCT里的记录该进程受到信号并把信号阻塞了的信号的一种数据结构。
阻塞信号集是如果信号属于这个集合则会对它挂起。
联系就是如果属于阻塞信号集则把它挂起并且添加到挂起信号集。
因此阻塞信号集不可能有重复的信号,挂起信号集里则可能记录了同一种信号。
解除阻塞后,信号会从挂起信号集中除去并且被处理程序处理。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP