先决条件: C中的fork() , 僵尸进程 僵尸状态 :在UNIX中使用fork()系统调用创建进程时,会复制父进程的地址空间。如果父进程调用wait()系统调用,则父进程的执行将暂停,直到子进程终止。在子进程终止时,会生成一个“SIGCHLD”信号,该信号由内核传递给父进程。父级在收到“SIGCHLD”后从进程表中读取子级的状态。即使子进程被终止,进程表中也有一个条目对应于存储状态的子进程。当父级收集状态时,此条目将被删除。因此,子进程的所有痕迹都将从系统中删除。如果父级决定不等待子级终止并执行其后续任务,则在子级终止时,退出状态不被读取。因此,即使在子进程终止后,进程表中仍保留一个条目。子进程的这种状态称为僵尸状态。
C
// A C program to demonstrate working of // fork() and process table entries. #include<stdio.h> #include<unistd.h> #include<sys/wait.h> #include<sys/types.h> int main() { int i; int pid = fork(); if (pid == 0) { for (i=0; i<20; i++) printf ( "I am Child" ); } else { printf ( "I am Parent" ); while (1); } } |
输出:
现在使用终端中的以下命令检查流程表 $ps-电弧炉
这是入口 不复存在 显示僵尸进程。
为什么我们需要阻止僵尸进程的产生? 每个系统有一个流程表。进程表的大小是有限的。如果生成的僵尸进程太多,则进程表将满。也就是说,系统将无法生成任何新流程,然后系统将停止。因此,我们需要防止僵尸进程的创建。
防止僵尸产生的不同方式
1.使用wait()系统调用: 当父进程调用wait()时,在创建子进程之后,它指示将等待子进程完成,并获取子进程的退出状态。父进程暂停(在等待队列中等待),直到子进程终止。必须理解的是,在此期间,父进程什么都不做,只是等待。
C
// A C program to demonstrate working of // fork()/wait() and Zombie processes #include<stdio.h> #include<unistd.h> #include<sys/wait.h> #include<sys/types.h> int main() { int i; int pid = fork(); if (pid==0) { for (i=0; i<20; i++) printf ( "I am Child" ); } else { wait(NULL); printf ( "I am Parent" ); while (1); } } |
2.忽略SIGCHLD信号: 当一个子进程终止时,相应的SIGCHLD信号被传递给父进程,如果我们调用“信号(SIGCHLD,SIG_IGN)”,那么系统将忽略SIGCHLD信号,并从进程表中删除子进程条目。因此,不会产生僵尸。但是,在这种情况下,家长无法知道孩子的退出状态。
C
// A C program to demonstrate ignoring // SIGCHLD signal to prevent Zombie processes #include<stdio.h> #include<unistd.h> #include<sys/wait.h> #include<sys/types.h> int main() { int i; int pid = fork(); if (pid == 0) for (i=0; i<20; i++) printf ( "I am Child" ); else { signal (SIGCHLD,SIG_IGN); printf ( "I am Parent" ); while (1); } } |
3.通过使用信号处理器: 父进程为SIGCHLD信号安装一个信号处理程序。信号处理程序在其中调用wait()系统调用。在这种情况下,当子级终止时,SIGCHLD被传递给父级。收到SIGCHLD后,相应的处理程序被激活,这反过来调用wait()系统调用。因此,父项几乎立即收集退出状态,并且清除流程表中的子项。因此,不会产生僵尸。
C
// A C program to demonstrate handling of // SIGCHLD signal to prevent Zombie processes. #include<stdio.h> #include<unistd.h> #include<sys/wait.h> #include<sys/types.h> void func( int signum) { wait(NULL); } int main() { int i; int pid = fork(); if (pid == 0) for (i=0; i<20; i++) printf ( "I am Child" ); else { signal (SIGCHLD, func); printf ( "I am Parent" ); while (1); } } |
输出:
这里没有 不复存在 i、 e.没有创建僵尸进程。
本文由 基什莱·维尔马 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄去评论-team@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。