C: 执行/分叉 > 僵尸进程

15

我想使用fork>exec程序创建许多子进程。许多进程很快就会结束(少于两分钟,有些甚至更短)。

我的第一个问题是,我将生成的进程放入后台运行:

./spawnbot > logging.txt
[CTRL+Z]
bg 1
disown

目前为止一切都很好。现在我不再看到spawnbot的任何消息了,它们直接进入logging.txt文件中。但是,每当创建一个新子进程时,我又可以在控制台上看到有关该子进程的所有信息。我现在想使用自己的管道启动每个子进程 - 有没有更好的方法来防止子进程在控制台上发布其输出消息?我应该将其重定向到/dev/null,还是可以通过C语言中的某个标志完成此操作?

另外,所有的子进程并没有真正停止。我在ps -ef命令中有很多进程。我该怎么办?如何d?

2个回答

23

首先是你的第二个问题!

你的子进程处于“僵尸”模式,因为内核认为你可能仍然想从它们那里检索返回值。

如果你没有意图从子进程中获取返回值,应该在父进程中设置SIGCHLD信号处理程序为SIG_IGN以使内核自动回收你的子进程。

signal(SIGCHLD, SIG_IGN);

第一个问题在很大程度上取决于您的实现方式..

但总的来说,在您调用 fork() 之后,应该使用 close() 关闭旧的文件描述符0和1,然后使用 dup2() 将它们设置为您想要的值。暂时没有例子,但希望这能指引您朝着正确的方向前进。


1
来自《Linux编程接口》的有趣引用:“请注意,即使SIGCHLD的默认处置是被忽略,显式地将处置设置为SIG_IGN也会导致这里描述的不同行为。在这方面,SIGCHLD在信号中被独特对待。” - ilstam

18

你的子进程正在被杀死。 僵尸进程, 也称为defunct进程(已死进程);zombies已经死了! 僵尸进程只是进程表中的条目,它没有任何代码或内存。

当一个进程死亡时(通过调用_exit或被信号杀死),它必须由其父进程回收。除了进程表中的条目之外,进程使用的所有资源都会消失。父进程必须调用waitwaitpid。一旦父进程已被通知子进程的死亡,并有机会读取子进程的退出状态,子进程在进程表中的条目也会消失:僵尸进程被回收。

如果您永远不想收到子进程的死亡通知,请忽略SIGCHLD信号;这告诉内核您不想了解子进程的命运,僵尸进程将自动被回收。

signal(SIGCHLD, SIG_IGN)
如果你只想在特定情况下被通知子进程的死亡,请使用带有 SA_NOCLDWAIT 标志的 sigaction 函数进行调用。当一个子进程死亡时,如果父进程正在执行 wait 系列函数中的任何一个,则会通知它子进程的死亡,并告知其退出状态;否则子进程的退出状态将被丢弃。
struct sigaction sa;
sa.sa_handler = &my_sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sa, NULL);
关于输出,除非您已经明确地重定向了它们(使用closeopendup或其他可能性),否则您的子进程会写入与父进程相同的位置。您的子进程可能正在将诊断消息打印到标准错误输出(毕竟这就是其用途)。
./spawnbot >logging.txt 2>&1

此外,由于您似乎想要将子进程与终端分离,因此您可能希望确保它们不会在您杀死终端时接收到SIGHUP。因此,请使用nohup

nohup ./spawnbot >logging.txt 2>&1 &
disown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接