shell 执行命令的过程
参考:https://www.youtube.com/watch?v=L6YqHxYHa7A 1:03:01
- Shell执行命令的流程
当你在Shell中输入
ls时,Shell的典型执行流程如下: - 解析命令:Shell解析输入的命令(如
ls)。 - Fork子进程:通过
fork()系统调用创建一个子进程(复制当前Shell进程的副本)。 - 子进程执行
exec:在子进程中调用execvp()等函数,将子进程的代码和数据替换为ls的代码。 - 父进程等待:父进程(原Shell)通过
wait()或类似函数等待子进程结束。 - 恢复Shell:子进程结束后,父进程继续运行,等待下一个命令。
- 为什么需要
fork()?- 防止Shell被替换:如果直接使用
exec()而不先fork(),当前Shell进程的代码和数据会被ls完全替换,导致执行完ls后Shell进程直接退出(用户会失去交互界面)。
- 防止Shell被替换:如果直接使用
- 隔离环境:子进程通过
fork()继承了Shell的环境(如环境变量、工作目录),但修改子进程的环境不会影响父进程Shell。
- 关键点澄清
exec的作用:exec系列函数会替换当前进程的代码和数据,但不创建新进程(进程ID不变)。因此必须在子进程中调用exec,才能保留父进程Shell。
fork的作用:fork创建了一个与父进程完全相同的子进程,之后通过exec让子进程“变身”为目标命令(如ls)。
- 特殊情况:内置命令
某些命令(如
cd、export)是Shell内置的,不需要fork和exec,而是由Shell直接修改自身环境。
- 流程图解
Shell进程 │ ├─ fork() │ ├─ 子进程 │ │ └─ exec("ls") → 替换为ls进程 │ │ └─ ls执行完毕,子进程退出 │ │ │ └─ 父进程(原Shell) │ └─ wait() → 等待子进程结束 │ └─ 恢复提示符,等待下一条命令
留下评论