我是C编程新手,我正在尝试创建一个“shell”,使用fork()
创建子进程,execvp
发送命令。我的目标是使我的程序能够同时运行进程,并等待。
例如,如果我输入emacs test.sml
,我希望我的shell打开带有此文件的emacs,并等待用户结束emacs。 (创建一个新的孩子,然后父母等待孩子完成)
但是,如果我输入emacs test.sml &
,那么我希望我的shell打开emacs,然后准备好接受新命令,即使用户保持emacs打开。 (创建一个新子项,然后父项已准备好进行新输入)。
我到目前为止编写的代码就是这样做的,但似乎wait()
只适用于第一个孩子。如果我执行以下操作:
emacs
emacs &
emacs
这是我的主要代码。安装程序获取用户输入,但在此处不相关:
int main(void)
{
char inputBuffer[MAX_LINE];
int background;
char *args[MAX_LINE/+1];
while(1) {
background = 0;
int mainpid = getpid();
printf("My PID is %d\n",mainpid);
printf(" COMMAND->\n");
setup(inputBuffer,args,&background);
pid_t pid; //Setting the PID
pid = fork();
if(pid < 0)
{
fprintf(stderr, "Fork Failed");
}
//background is 1 if the command ends with &
if(background == 1)
{
if(pid==0)
{
printf("Child should run concurrently with parent\n");
int pid = getpid();
int ppid = getppid();
printf("Child PID %d\n", pid);
printf("Child PPID %d\n", ppid);
execvp(inputBuffer, args);
exit(1);
}
else
{
printf("Parent not waiting\n");
int pid = getpid();
printf("Parent PID %d\n", pid);
}
}
else if(background != 1)
{
if(pid==0)
{
printf("Child running and parent waiting\n");
int pid = getpid();
int ppid = getppid();
printf("Child PID %d\n", pid);
printf("Child PPID %d\n", ppid);
execvp(inputBuffer, args);
exit(1);
}
else
{
printf("Parent WAIT\n");
wait(NULL);
printf("Parent done waiting\n");
int pid = getpid();
printf("Parent PID %d\n", pid);
}
}
}
}
任何帮助非常感谢
答案 0 :(得分:3)
如果你在后台运行一个进程,而不是等待,稍后它可能会(将)死掉。此时,您可能正在等待同步启动的另一个进程。
您应该循环调用wait()
或waitpid()
,查找您刚开始的流程的PID,并清理其他僵尸流程:
int status;
int corpse;
while ((corpse = waitpid(-1, &status, 0)) > 0 && corpse != new_pid)
...process the death of 'corpse' with exit status 'status'...
循环体中的处理可能与分号一样微不足道;它可能会从后台运行的进程列表中移除尸体(也许可能会带入前台)等等。虽然你可以指定new_pid
作为waitpid()
的第一个参数,当你不需要这样做时,你会把其他进程当作僵尸。在某些时候,你必须清理僵尸 - 当你等待其他东西完成时更好?您可以改为使用wait()
:
while ((corpse = wait(&status)) > 0 && corpse != new_pid)
答案 1 :(得分:0)
execvp()可能会失败。如果失败,可能看起来父母没有等待
请尝试更改此
execvp(inputBuffer, args);
exit(1);
到
if(execvp(inputBuffer, args)<0)
{
printf("\n execvp failed");
exit(1);
}
并查看