gpt4 book ai didi

c - 关于在我的虚拟 shell 中使用 fork() 和子进程的后台进程

转载 作者:太空狗 更新时间:2023-10-29 16:29:42 27 4
gpt4 key购买 nike

我正在尝试用 C 语言创建一个简单的 shell 程序。我需要它做的是为用户提供一个提示,他们可以在其中运行其他本地程序。我可以很好地完成这部分,使用 fork(),其中父进程在子进程上等待(),而子进程 execvp() 是程序。

但是,如果“&”字符附加到用户命令的末尾,我需要他们的程序在后台运行,这意味着我需要父进程不要等待子进程,而是立即返回提示用户,同时允许后台进程继续运行,但不允许它在屏幕上显示任何内容。我只是想通过 ps 命令检查它是否仍然存在。

我试图理解使用 fork() 创建子进程背后的想法,然后让子进程再次 fork() 以创建某种孙子进程,然后立即退出 () - 子进程。即,使孙子成为孤儿。据说这允许 parent 仍然等待 child ,但由于 child 实际上几乎立即结束,所以它根本不等待?关于僵尸疯狂的事情?我不知道。我遇到的几个站点似乎都推荐将此作为在后台运行进程的一种方式。

但是,当我尝试执行此操作时,我发现程序流程中发生了一些疯狂的事情,“后台”进程继续在屏幕上显示输入,我真的不确定从这里到哪里去。

这是我对代码的实现,我确信这是完全错误的。我只是想知道这整个孙子的事情是否是我需要走的路,如果是这样,我的代码有什么问题?

36 int main(int argc, char *argv[])
37 {
38 char buffer[512];
39 char *args[16];
40 int background;
41 int *status;
42 size_t arg_ct;
43 pid_t pid;
44
45 while(1)
46 {
47 printf("> ");
48 fgets(buffer, 512, stdin);
49 parse_args(buffer, args, 16, &arg_ct);
50
51 if (arg_ct == 0) continue;
52
53 if (!strcmp(args[0], "exit"))
54 {
55 exit(0);
56 }
57
58 pid = fork(); //here I fork and create a child process
61
62 if (pid && !background) //i.e. if it's the parent process and don't need to run in the background (this is the part that seems to work)
63 {
64 printf("Waiting on child (%d).\n", pid);
65 pid = wait(status);
66 printf("Child (%d) finished.\n", pid);
67 }
68 else
69 {
70 if (background && pid == 0) { //if it's a child process and i need to run the command in background
71
72 pid = fork(); //fork child and create a grandchild
73 if (pid) exit(0); //exit child and orphan grandchild
74
75 execvp(args[0], args); //orphan execs the command then exits
76 exit(1);
77
78 } else exit(0);
79 }
80 }
81 return 0;
82 }

P.S. 明确地说,我需要我在后台运行的进程不再发出声音,即使它有无限循环的打印语句或其他东西。我只是想通过 ps -a 或其他方式确保它仍在后台运行。

对于令人困惑的解释,我深表歉意,我只是不知道如何更好地解释它。

提前致谢

P.P.S 我将实现它,以便每个后续命令都将确定“背景”的 bool 值,抱歉造成混淆

最佳答案

您不想在 shell 中使用双重 fork() 方法 - 这是为了编写特别想逃避运行它们的 shell 监督的守护进程。

相反,在现有 shell 中复制 & 行为的方法是调用 fork(),然后在子调用中调用 setpgid(0, 0 ); 将子进程放入一个新的进程组。父级继续(可能在打印子级的 PID 之后)——它不调用 wait()

每个终端只能有一个前台进程组,即当前允许向终端发送输出的进程组。这将保留您的 shell 所属的进程组,因此您的 shell 将保留在前台。

如果一个后台进程组试图从终端读取,它会被发送一个信号来停止它。仍然允许向终端输出 - 这是正常的(在您的常规 shell 中尝试 ls &)。要在您的 shell 中执行 fg 命令,您需要 tcsetpgrp() 函数来更改前台进程组。

您还需要使用 WNOHANG 选项定期调用 waitpid() - 例如,在显示 shell 提示符之前立即调用。这将允许您检测后台进程何时退出或停止(或者,您可以处理 SIGCHLD 信号)。

关于c - 关于在我的虚拟 shell 中使用 fork() 和子进程的后台进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8319484/

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