C 中的信号处理

发布于 2024-10-07 21:22:08 字数 861 浏览 2 评论 0原文

我正在研究信号在 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 NinjaGhost 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

︶ ̄淡然 2024-10-14 21:22:08

让我们逐行检查一下。设置信号处理程序,然后分叉。孩子打印出“Ghost”并退出。父进程让子进程打印“Phantom”并退出。然后家长打印“Ninja”。

所以你确实遇到了竞争条件。如果父进程在子进程打印“Ghost”之前触发 SIGUSR1,那么您将得到 Phantom Ninja,或者可能是 Ninja Phantom(确实会杀死阻止?)

但是,如果您无法及时关闭信号,那么您将收到Ghost Ninja,因为子进程在父进程发出信号之前完成。我认为相反的情况是不可能的。

现在可以想象,信号可能恰好准时到达printfexit之间,在这种情况下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 get Phantom Ninja, or perhaps Ninja 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 the exit, in which case Ghost would finish, followed by Phantom then Ninja - 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.

扮仙女 2024-10-14 21:22:08

让我们首先用行号标记行,如下所示:

signal(SIGUSR1, handler1); //installing signal handler ---- 1
   if((pid1 = fork()) == 0) { //forking                ---- 2
       printf("Ghost");                                ---- 3
       exit(0);                                        ---- 4
 }
   kill(pid1, SIGUSR1);                                ---- 5
   printf("Ninja");                                    ---- 6

现在使用上面的代码,如果
子进程首先执行并且
如果先执行 3,则子进程被挂起,父进程开始执行 5。这将打印 GhostPhantomNinja

但是,无法确定明确的顺序。

Lets mark the lines with line numbers first as follows:

signal(SIGUSR1, handler1); //installing signal handler ---- 1
   if((pid1 = fork()) == 0) { //forking                ---- 2
       printf("Ghost");                                ---- 3
       exit(0);                                        ---- 4
 }
   kill(pid1, SIGUSR1);                                ---- 5
   printf("Ninja");                                    ---- 6

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.

剧终人散尽 2024-10-14 21:22:08

这里有两个非确定性因素,它们都取决于操作系统:上下文切换何时发生,以及信号何时到达。

既然你无法控制这些,我会回答任何顺序都是可能的。尝试在命令之间插入 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.

转身泪倾城 2024-10-14 21:22:08
//#include <sys/types.h>
#include<stdlib.h>
void handler1(int sig) {
 printf("Phantom\n");
 waitpid(-1,NULL,0);
 //sexit(0);
}
int main()
{
   pid_t pid1;
   signal(SIGUSR1, handler1); //installing signal handler
        printf("my pid is %d ha ha parent..\n",getpid());
   //if((pid1 = fork()) == 0) { //forking
       pid1=fork();
       if(pid1==0)//in childe processs
       {
    printf("my pid is %d ha ha child..\n",getpid());
       printf("Ghost\n");
       sleep(6);
       exit(0);
   }
   else{
  //sleep(4); 
   kill(pid1, SIGUSR1);
   sleep(3);
   printf("Ninja\n");
   return 0;
}
}
//#include <sys/types.h>
#include<stdlib.h>
void handler1(int sig) {
 printf("Phantom\n");
 waitpid(-1,NULL,0);
 //sexit(0);
}
int main()
{
   pid_t pid1;
   signal(SIGUSR1, handler1); //installing signal handler
        printf("my pid is %d ha ha parent..\n",getpid());
   //if((pid1 = fork()) == 0) { //forking
       pid1=fork();
       if(pid1==0)//in childe processs
       {
    printf("my pid is %d ha ha child..\n",getpid());
       printf("Ghost\n");
       sleep(6);
       exit(0);
   }
   else{
  //sleep(4); 
   kill(pid1, SIGUSR1);
   sleep(3);
   printf("Ninja\n");
   return 0;
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文