我正在尝试在C中创建一个简单的外壳程序。我需要做的是为用户提供一个可以运行其他本地程序的提示。我可以使用fork()在孩子上waits()和子execvp()的程序。

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

我试图理解使用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 需要明确的是,我需要在后台运行的过程,即使它具有无限的印刷语句循环或其他内容,也需要再发出声音。我只想确保它仍然通过PS -A或其他内容在后台运行。

抱歉,我只是不知道如何更好地解释它。

提前致谢

pps 我将实施它,以便每个后续命令都会确定“背景”的布尔值,对此感到抱歉

有帮助吗?

解决方案

您不想使用双重fork() 外壳中的方法 - 用于编写守护程序,这些守护程序是要特别想摆脱运行它们的外壳的监督。

相反,复制行为的方式 & 在现有的外壳中是致电 fork(), ,然后在孩子的电话中 setpgid(0, 0); 把孩子纳入一个新 过程组. 。父母只是继续(也许在打印之后 PID 孩子的) - 不打电话 wait().

每个终端只能具有一个前景过程组,该过程组是当前允许将输出发送到终端的过程组。这将保留您的外壳是成员的过程组,因此您的外壳将保留在前景中。

如果背景过程组试图从终端读取,则将向其发送信号以停止它。仍然允许输出到终端 - 这是正常的(尝试 ls & 在您的常规外壳中)。实施 fg 在外壳中的命令,您将需要 tcsetpgrp() 更改前景过程组的功能。

您还想打电话 waitpid()WNOHANG 定期选项 - 在显示外壳提示之前立即说。这将使您能够检测到背景过程何时退出或停止(或者,您可以处理 SIGCHLD 信号)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top