我正在编写自定义shell command language interpreter,我发现其他shell使用system()调用来执行管道或高级shell程序。使用exec
和fork
执行管道而不是拨打system()
是不是更好?例如,如果它是救援shell或其他一些情况,那么您可能无法访问资源system()
。
/* With the standard output plumbing sorted, execute Nth command */
static void exec_nth_command(int ncmds, char ***cmds) {
assert(ncmds >= 1);
if (ncmds > 1) {
pid_t pid;
Pipe input;
if (pipe(input) != 0)
err_sysexit("Failed to create pipe");
if ((pid = fork()) < 0)
err_sysexit("Failed to fork");
if (pid == 0) {
/* Child */
exec_pipe_command(ncmds - 1, cmds, input);
}
/* Fix standard input to read end of pipe */
dup2(input[0], 0);
close(input[0]);
close(input[1]);
}
execvp(cmds[ncmds - 1][0], cmds[ncmds - 1]);
err_sysexit("Failed to exec %s", cmds[ncmds - 1][0]);
/*NOTREACHED*/
}
/* Given pipe, plumb it to standard output, then execute Nth command */
static void exec_pipe_command(int ncmds, char ***cmds, Pipe output) {
assert(ncmds >= 1);
/* Fix stdout to write end of pipe */
dup2(output[1], 1);
close(output[0]);
close(output[1]);
exec_nth_command(ncmds, cmds);
}
/* Execute the N commands in the pipeline */
void exec_pipeline(int ncmds, char ***cmds) {
assert(ncmds >= 1);
pid_t pid;
if ((pid = fork()) < 0)
err_syswarn("Failed to fork");
if (pid != 0)
return;
exec_nth_command(ncmds, cmds);
}
正如您从上面的代码中看到的那样,我从未在我的shell中调用system()
,但这是有充分理由的吗?
答案 0 :(得分:3)
由于您正在实现一个新shell,因此使用system(3)
内部会显得很奇怪,因为system(3)
使用系统默认shell,这几乎肯定是与您正在实现的shell不同的shell。 / p>
另外,{{1}}确实会使某些类型的错误处理变得更难 - 您无法完全了解启动子进程后发生的情况。
答案 1 :(得分:1)
它有自己的优点和缺点。实现很可能在其中调用fork
和exec
,因此为了使用fork / exec而放弃它是没有意义的。事实上,如果你想在旅途中运行一个命令,不关心它的输入/输出,退出状态等,那么调用system
会很方便。
另一方面,如果你想处理输入/输出重定向,或者为命令添加额外的fds,或者获得准确的退出状态,或者向子进程发送信号等等,你需要做的fork / exec就是你自己。
请注意,system
的返回值及其用于运行命令的命令处理器都是实现定义的,因此如果您正在使用便携式shell,则可能需要避免调用它。