use*_*375 6 c unix linux fork process
我有一个父进程可能产生许多子进程的情况.我想要实现的是,如果父进程被终止或者它退出,那么它的所有子进程应该与父进程终止.
在帖子(下面的链接)中,我找到了通过让父进程成为组长来存档的建议.如果我理解正确,这也是过程组的主要目的.我对吗?
Post也提到了prctl(PR_SET_PDEATHSIG,SIGHUP); 和其他一些方法,但它们是以太网操作系统特定的,否则不会如此优雅.
我已经写了一个小的演示来试图更好地理解事物,但它并不像我期望的那样工作.我究竟做错了什么?
//https://www.andrew.cmu.edu/course/15-310/applications/homework/homework4/terminalgroups1.html
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
int main()
{
int status;
int cpid;
int ppid;
ppid = getpid();
printf("parent: %d\n", ppid);
if (!(cpid=fork()))
{
printf("child: %d\n", getpid());
if(setpgid(0,ppid) == -1)
printf("child setpgid errno %s\n", strerror(errno));
else
printf("child gid %d\n", getpgid(0));
pause();
printf("child exited\n");
exit (-1);
}
if (cpid < 0)
exit(-1);
setpgid(0, ppid);
if(setpgid(0,0) == -1)
printf("parent setpgid erno %s\n", strerror(errno));
else
printf("parrent gid %d\n", getpgid(0));
sleep(7);
printf("parent exit\n");
exit(0);
}
Run Code Online (Sandbox Code Playgroud)
这篇文章涉及以下建议:*如何让父母退出后儿童过程死亡?
请注意,仅在非常有限的情况下才会向子进程发送信号。 POSIX说:
如果该进程是一个控制进程,SIGHUP 信号将被发送到属于调用进程的控制终端的前台进程组中的每个进程。
如果进程是控制进程,则与会话关联的控制终端应与会话解除关联,允许它被新的控制进程获取。
如果进程退出导致进程组成为孤立进程,并且新孤立进程组的任何成员停止,则应向新孤立进程组中的每个进程发送 SIGHUP 信号和 SIGCONT 信号.
控制过程的定义是:
与控制终端建立连接的会话领导者。如果该终端随后不再是该会话的控制终端,则会话领导者不再是控制进程。
通常,您的进程不会成为与控制终端(通常是您的 shell)建立连接的会话领导者。
如果 POSIX 的其他部分适用,请通知我。
我对您的代码 ( termkids.c
) 的这种改编做了一些测试:
#include "posixver.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
static void sigcatcher(int signum)
{
printf("%d: Signal caught: %d\n", (int)getpid(), signum);
exit(1);
}
int main(void)
{
int cpid;
int ppid;
ppid = getpid();
printf("Parent PID: %d\n", ppid);
printf("Initial PGID: %d\n", (int)getpgid(0));
if (setpgid(0, 0) != 0)
{
fprintf(stderr, "setpgid() failed (%d: %s)\n", errno, strerror(errno));
return 1;
}
printf("Revised PGID: %d\n", (int)getpgid(0));
if ((cpid=fork()) < 0)
{
fprintf(stderr, "fork() failed (%d: %s)\n", errno, strerror(errno));
return 1;
}
else if (cpid == 0)
{
cpid = getpid();
printf("Child PID: %d\n", cpid);
printf("Child PGID: %d\n", (int)getpgid(0));
(void)signal(SIGTERM, sigcatcher);
(void)signal(SIGHUP, sigcatcher);
pause();
printf("%d: child exited\n", cpid);
return(-1);
}
printf("Parent - sleeping\n");
sleep(7);
printf("Parent exits\n");
return(0);
}
Run Code Online (Sandbox Code Playgroud)
示例输出:
$ ./termkids
Parent PID: 17701
Initial PGID: 17701
Revised PGID: 17701
Parent - sleeping
Child PID: 17702
Child PGID: 17701
Parent exits
$ ps
PID TTY TIME CMD
388 pts/5 00:00:00 bash
17702 pts/5 00:00:00 termkids
17707 pts/5 00:00:00 ps
$ kill 17702
17702: Signal caught: 15
$
Run Code Online (Sandbox Code Playgroud)
请注意,kill 17702
是在父进程完成后几分钟发送的。
小智 2
您可以使用atexit注册一个函数,该函数向具有相同进程组id的所有进程发送SIGHUP信号。当父进程退出时,这将达到向所有子进程发送信号的预期效果。但是,请注意,子级中的 SIGHUP 信号处理程序将导致子级立即退出,而不会从暂停()返回并打印子级退出消息。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <stddef.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/termios.h>
#include <sys/types.h>
void killall()
{
kill(0, SIGHUP);
}
int main()
{
int status;
int cpid;
int ppid;
if (atexit(killall) != 0)
{
fprintf(stderr, "atexit failed with %d", errno);
exit(-1);
}
ppid = getpid();
printf("parent: %d\n", ppid);
if (!(cpid=fork()))
{
printf("child: %d\n", getpid());
if(setpgid(0,ppid) == -1)
printf("child setpgid errno %s\n", strerror(errno));
else
printf("child gid %d\n", getpgid(0));
pause();
printf("child exited\n");
exit (-1);
}
if (cpid < 0)
exit(-1);
setpgid(0, ppid);
if(setpgid(0,0) == -1)
printf("parent setpgid erno %s\n", strerror(errno));
else
printf("parent gid %d\n", getpgid(0));
sleep(7);
printf("parent exit\n");
exit(0);
}
Run Code Online (Sandbox Code Playgroud)