4

问题是标题。我不明白为什么在执行“ls”后终端会立即关闭。Linux shell 是这样的:

1.while (1) {
2. char *cmd = read_command();
3. int child_pid = fork();
4. if (child_pid == 0) {
5. exec(cmd);
6. }else {
7.waitpid(child_pid);
8.}
9.}

因此,如果我们在 shell 中运行 'exec ls',则 cmd 是一个 'exec ls' 字符串。第 3 行创建了一个子进程。在第 5 行,exec(cmd) 将替换子进程,但不会影响父进程。如果父进程不受影响,那为什么终端会关闭呢?

请告诉我上面推理中的缺陷。

4

3 回答 3

6

如果你运行ls,你的shell进程将启动另一个进程来运行ls程序,然后它会等待它完成。完成后,控制权返回给 shell。

使用exec ls,您实际上将当前进程中的 shell 程序替换为该程序,这样,当它完成时,没有 shell 等待它。ls

最有可能的是,您将拥有一个终端程序或init作为父程序,这将在您的进程退出时接管。这就是你的外壳消失的原因,因为你明确告诉它。

有关(非执行)情况的解释,请参阅此答案。shell/ls


至于您的更新,shell 并不总是创建一个单独的进程来做事。有大量内部命令(例如cdor alias)不涉及创建其他进程(这当然取决于您的 shell,但作为一个示例,您可以通过在命令提示符bash下输入来查看内部命令man bash-builtins)。

exec就是其中之一。它只是用您指定的程序替换shell 本身(即,不是分叉的子进程)。这就是为什么它不像你想象的那样工作。

于 2013-01-28T03:11:42.053 回答
3

Exec 用另一个进程覆盖当前进程。通常,当您调用“ls”时,会创建一个作为 shell 的子进程运行的新进程。“exec ls”用“ls”进程覆盖你当前的shell。因此,一旦“ls”终止,您的终端就会关闭。

于 2013-01-28T03:10:26.000 回答
2

exec用新的进程映像覆盖正在运行的进程。因此,在您当前的进程中,您正在运行的 shell 被ls可执行映像覆盖,一旦ls退出,进程就会关闭。

于 2013-01-28T03:10:07.050 回答