少于 1 分钟阅读 次阅读

参考:https://www.youtube.com/watch?v=L6YqHxYHa7A 1:03:01

  1. Shell执行命令的流程 当你在Shell中输入ls时,Shell的典型执行流程如下:
  2. 解析命令:Shell解析输入的命令(如ls)。
  3. Fork子进程:通过fork()系统调用创建一个子进程(复制当前Shell进程的副本)。
  4. 子进程执行exec:在子进程中调用execvp()等函数,将子进程的代码和数据替换为ls的代码。
  5. 父进程等待:父进程(原Shell)通过wait()或类似函数等待子进程结束。
  6. 恢复Shell:子进程结束后,父进程继续运行,等待下一个命令。

  1. 为什么需要fork()
    • 防止Shell被替换:如果直接使用exec()而不先fork(),当前Shell进程的代码和数据会被ls完全替换,导致执行完ls后Shell进程直接退出(用户会失去交互界面)。
  • 隔离环境:子进程通过fork()继承了Shell的环境(如环境变量、工作目录),但修改子进程的环境不会影响父进程Shell。

  1. 关键点澄清
    • exec的作用:exec系列函数会替换当前进程的代码和数据,但不创建新进程(进程ID不变)。因此必须在子进程中调用exec,才能保留父进程Shell。
  • fork的作用:fork创建了一个与父进程完全相同的子进程,之后通过exec让子进程“变身”为目标命令(如ls)。

  1. 特殊情况:内置命令 某些命令(如cdexport)是Shell内置的,不需要forkexec,而是由Shell直接修改自身环境。

  1. 流程图解
    Shell进程
    │
    ├─ fork()
    │   ├─ 子进程
    │   │   └─ exec("ls") → 替换为ls进程
    │   │       └─ ls执行完毕,子进程退出
    │   │
    │   └─ 父进程(原Shell)
    │       └─ wait() → 等待子进程结束
    │
    └─ 恢复提示符,等待下一条命令
    

留下评论