gpt4 book ai didi

c - 父进程在 Linux shell 上等待上一个子进程

转载 作者:行者123 更新时间:2023-11-30 17:54:12 34 4
gpt4 key购买 nike

我有一个程序可以 fork 一个进程,并确定子进程是否应该在前台和后台运行。我在 fork 之前调用信号函数来处理子信号,以确保死亡的子进程不会变成僵尸。

到目前为止,我的程序工作正常,它创建一个子进程,并在用户输入带有“&”的命令时在后台运行它,并在用户输入不带“&”的命令时在前台运行它。

但是,我发现了一个非常有趣的行为。假设我调用这个操作序列:

sleep 5 &
ls

第一个命令可以正常工作,父进程不会等待 sleep 5 完成。但是,当我运行“ls”时,它会打印该文件夹中的所有文件(这很好),但随后 shell 被卡住,等待前面的“sleep 5 &”完成...

为什么会出现这种情况?我的子进程和父进程的代码( fork 后)如下所示:

 if (pid == 0)
{
// child process, execute stuff
execv();
}
else if (pid > 0)
{
// parent process: call waitpid to wait for foreground child
}

我尝试做一些研究,但找不到任何可以帮助我的东西。我尝试通过在 execv() 之前调用它来对子进程使用“set session-id”,但它阻止我的子进程在终端上打印任何内容。任何帮助将不胜感激。谢谢!

最佳答案

    #define _XOPEN_SOURCE 700
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

void run_command(void)
{
char *cmd = NULL, *arg;
size_t n, l;
bool background;
pid_t child;

l = getline(&cmd, &n, stdin);
cmd[l-1] = 0;
l--;

if (cmd[l-1] == '&') {
background = true;
cmd[l-1] = 0;
l--;
}
else
background = false;

arg = strchr(cmd, ' ');
if (arg) {
*arg = 0;
arg++;
}

child = fork();

if (child) {
if (!background)
waitpid(child, NULL, 0);
}
else {
execlp(cmd, cmd, arg, NULL);
exit(-1);
}

free(cmd);
}

int main(void)
{
sigset_t set;
struct sigaction sig;

sigemptyset(&set);
sig.sa_handler = SIG_DFL;
sig.sa_mask = set;
sig.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sig, NULL);

while(!feof(stdin)) run_command();
}

这按预期工作:

hdante@aielwaste:~/code$ ./shell 
pwd
/home/hdante/code
ls /home
hdante
sleep 5
ls /
bin dev initrd.img lib32 lost+found opt run srv usr vmlinuz.old
boot etc initrd.img.old lib64 media proc sbin sys var
cdrom home lib libnss3.so mnt root selinux tmp vmlinuz
sleep 5&
xedit&
ls /
bin dev initrd.img lib32 lost+found opt run srv usr vmlinuz.old
boot etc initrd.img.old lib64 media proc sbin sys var
cdrom home lib libnss3.so mnt root selinux tmp vmlinuz

在上面的示例中,sleep 5 正确阻塞,而 sleep 5& 和 xedit& 则不然。

不查看代码,就不可能知道问题出在哪里。但请注意我处理僵尸进程的方式:我在 sa_flags 中使用 SA_NOCLDWAIT,这样我就不需要跟踪 pid。另外,我使用 waitpid() 等待前台子进程。我认为这就是问题所在。您的代码很可能正在调用 wait() 而不是 waitpid()。不同之处在于 wait() 等待所有子进程。

关于c - 父进程在 Linux shell 上等待上一个子进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15078979/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com