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



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

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

我试图理解使用fork()创建子进程背后的想法,然后让子fork()再次创建各种各样的孙子,然后立即退出()-退出子进程。也就是说,让孙子成为孤儿。假设这允许父进程仍然等待子进程,但由于子进程实际上几乎立即结束,就像它根本没有等待一样?关于僵尸的疯狂?我不知道。我遇到的几个站点似乎都推荐使用这种方式在后台运行进程。

然而,当我尝试这样做时,我得到了疯狂的事情发生在程序的流程中,"后台"进程继续在屏幕上显示输入,我真的不知道从这里去哪里。

这是我的代码实现,我确信这是相当错误的。我只是想知道这整个孙子的事情甚至是我需要采取的路线,如果是这样的话,我的代码有什么问题?

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 }

注:要清楚,我需要我在后台运行的进程永远不会再发出声音,即使它有一个无限循环的打印语句或其他东西。我只是想通过ps -a或其他方式确保它仍然在后台运行。

很抱歉我的解释让人困惑,我只是不知道如何解释得更好。

Thanks in advance

最大功率S我将实现它,以便每个后续命令将确定'background'的布尔值,对不起,对于混乱

您不希望在shell中使用double- fork()方法-这是用于编写特别想要逃避运行它们的shell的监督的守护进程。

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

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

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

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

最新更新