C 中的信号处理
我正在研究信号在 C 中是如何工作的。 这是旧考试中的一个例子:
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
//#include <sys/types.h>
void handler1(int sig) {
printf("Phantom");
exit(0);
}
int main()
{
pid_t pid1;
signal(SIGUSR1, handler1); //installing signal handler
if((pid1 = fork()) == 0) { //forking
printf("Ghost");
exit(0);
}
kill(pid1, SIGUSR1);
printf("Ninja");
return 0;
}
到目前为止,GCC 给了我两个答案 Ghost Ninja
和 Ghost Ninja
。 幻影忍者
。它能产生Ghost Phantom Ninja
或任何其他由3个名字组成的组合吗?
我认为它可能产生 3 个名字的一种方式是: fork,在Child中运行,打印Ghost
,exit(0) =>在父级中,接受/处理信号并从信号处理程序打印Phantom
,杀死子级,打印Ninja
。但我不确定我的“理论”是否站得住脚。
另外,kill(pid1, SIGUSR1)会调用handler()吗?
谢谢 !
I am figuring how signals work in C.
Here is one of the examples taken from old exams:
#include<signal.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>
//#include <sys/types.h>
void handler1(int sig) {
printf("Phantom");
exit(0);
}
int main()
{
pid_t pid1;
signal(SIGUSR1, handler1); //installing signal handler
if((pid1 = fork()) == 0) { //forking
printf("Ghost");
exit(0);
}
kill(pid1, SIGUSR1);
printf("Ninja");
return 0;
}
So far, GCC gives me two answers Ghost Ninja
& Ninja Phantom
. Could it produce Ghost Phantom Ninja
or any other combination made of 3 names ?
One way I see it could possibly produce 3 names is:
Fork, run in Child, print Ghost
, exit(0) => in Parent, accept/process signal and from signal Handler print Phantom
, kill child, print Ninja
. But I am not sure if my "theory" holds the ground.
Also, would the kill(pid1, SIGUSR1)
invoke handler()
?
Thanks !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
让我们逐行检查一下。设置信号处理程序,然后分叉。孩子打印出“Ghost”并退出。父进程让子进程打印“Phantom”并退出。然后家长打印“Ninja”。
所以你确实遇到了竞争条件。如果父进程在子进程打印“Ghost”之前触发
SIGUSR1
,那么您将得到Phantom Ninja
,或者可能是Ninja Phantom
(确实会杀死阻止?)但是,如果您无法及时关闭信号,那么您将收到
Ghost Ninja
,因为子进程在父进程发出信号之前完成。我认为相反的情况是不可能的。现在可以想象,信号可能恰好准时到达
printf
和exit
之间,在这种情况下Ghost< /code> 将完成,然后是
Phantom
,然后是Ninja
- 或者反过来,我想。它对操作系统计时非常挑剔和敏感。
@Everyone - 未经测试!请随意反驳我,但我和OP一样有兴趣知道为什么。
Let's examine this line-by line. Set up a signal handler, then fork. The child prints "Ghost" and exits. The parent makes the child print "Phantom" and exit. Then the parent prints "Ninja".
So you've really got a race condition. If the parent fires its
SIGUSR1
before the child prints "Ghost", then you'll getPhantom Ninja
, or perhapsNinja Phantom
(does kill block?)But, if you can't get the signal off in time, then you'll get
Ghost Ninja
as the child finishes before the parent signals. I don't think the reverse is possible.Now it is conceivable that the signal could be exactly on time to hit between the
printf
and theexit
, in which caseGhost
would finish, followed byPhantom
thenNinja
- or the reverse again, I think.It's really finicky and sensitive to OS timing.
@Everyone - not tested! Feel free to contradict me, but I'll be as interested to know why as the OP.
让我们首先用行号标记行,如下所示:
现在使用上面的代码,如果
子进程首先执行并且
如果先执行 3,则子进程被挂起,父进程开始执行 5。这将打印 GhostPhantomNinja
但是,无法确定明确的顺序。
Lets mark the lines with line numbers first as follows:
Now with the above code, if
Child executes first and
if 3 is executed first, then child is suspended and parent starts executing with 5. This will print GhostPhantomNinja
However, a definite order can not be determined.
这里有两个非确定性因素,它们都取决于操作系统:上下文切换何时发生,以及信号何时到达。
既然你无法控制这些,我会回答任何顺序都是可能的。尝试在命令之间插入 wait() 并查看是否获得所需的结果。
You have two non deterministic factors here, which are both depends on the OS: when will the context switching occur, and when will the signal arrive.
Since you can't control those, I'd answer that any order is possible. Try inserting wait() between command and see if you get the desired results.