【发布时间】:2016-06-15 01:49:51
【问题描述】:
我正在实现一个外壳。
当尝试更改目录以外的命令时,execvp() 运行,子进程终止并创建一个新子进程。当我更改目录时,孩子不会终止并创建一个新的孩子。这是我的代码示例:
for(;;) {
printf("bash: ");
parse();
...
pid_t pid = fork()
if (pid == 0)
if (!strcmp(line[0], "cd"))
if (!line[1]) (void) chdir(getenv("HOME"));
else (void) chdir(line[1]);
else execvp(line[0], line);
...
if (pid > 0) {
while (pid == wait(NULL));
printf("%d terminated.\n", pid);
}
}
cd ../; ls; 运行正常,但我必须Ctrl+D 两次才能结束程序。
但是,如果我通过管道传输相同的信息(即mybash < chdirtest),它会正确运行一次,终止子进程,然后直接在原始文件中再次运行,然后终止最后一个子进程。
【问题讨论】:
-
当您运行
cd时,显示的(不完整)代码将不会调用execvp。相反,它将执行chdir,然后继续运行下一个for循环迭代,该迭代将调用fork。这就是cd情况下第一个子进程不退出的原因。 -
欢迎来到 Stack Overflow。请尽快阅读About 页面。我的直接看法是,这里没有足够的信息让我们能够回答——魔鬼在细节中,而细节缺失。但是,@kaylum 至少解决了部分问题,并且可能已经确定了主要问题。 (我会观察到
if (pid == 0)之后的条件让我石化——没有足够的大括号,如果execvp()或chdir()失败,则没有错误处理。)请阅读如何创建 MCVE (minimal reproducible example) 和然后提供一个。 -
@kaylum 我不希望
cd调用execvp()。我希望它更改目录,循环返回,然后运行下一行而不出现问题。 -
很好,但你的问题是为什么孩子不退出。这是试图解释原因。如果您认为该解释不正确,请指出原因。如果您不希望它再次分叉,那么
cd案例应该调用chdir,然后继续解析并执行下一个命令,而不需要另一个fork。 -
"创建一个 bash 程序" 不,你正在实现一个 shell(可能类似于 bash)