当你运行程序时到底会发生什么

发布: (2026年2月19日 GMT+8 02:03)
5 分钟阅读
原文: Dev.to

Source: Dev.to

从按键到执行

当你输入命令并按下 Enter 键时,程序会在毫秒级别启动。操作系统协调了一系列步骤,涉及 shell、内核、CPU 调度器和内存管理。

Shell → 内核交互

  1. Shell 解析命令 – Shell 作为普通用户进程运行。
  2. Shell 请求内核 启动一个新程序。

内核随后:

  • 在内存中分配进程结构体
  • 分配唯一的 PID(进程标识符)
  • 从磁盘加载可执行文件
  • 将代码和数据映射到虚拟内存
  • 将进程放入就绪队列

可执行文件包含机器指令和元数据。加载程序将这些段映射后,进程已存在,但必须等待 CPU 时间。

特权模式

  • 用户模式 – 运行应用程序代码;硬件访问受限。
  • 内核模式 – 拥有完整特权,控制硬件、内存和设备。

当程序需要系统资源时,它会发出 系统调用,这会触发受控的切换到内核模式。内核验证请求,执行操作,然后将控制权返回用户模式,从而保护系统免受错误程序的影响。

Unix‑Style Program Launch (fork‑exec)

  1. fork – 创建一个子进程,子进程获得父进程内存空间和文件描述符的副本。父子进程从同一点继续执行。
  2. exec – 子进程用新的程序映像替换其内存。PID 保持不变,只有代码和数据被更换。

Shell 按如下模式工作:

  • Shell 调用 fork
  • 子进程调用 exec 并传入你的命令
  • 父 Shell 根据作业规则等待或继续执行

这种模型使进程管理保持简单且可预测。

进程生命周期

状态描述
新建进程已创建
就绪进程等待 CPU 时间
运行进程在核心上执行
等待进程因 I/O 或其他事件而暂停
已终止进程退出

调度

调度程序使用诸如 FCFS、SJF、SRTF、Round‑Robin 等算法来选择下一个要运行的就绪进程。大多数调度程序使用优先级和 时间片——即进程在发生上下文切换前可以运行的时长限制。

在一次上下文切换期间,内核会:

  • 保存当前进程的 CPU 寄存器
  • 加载下一个进程的寄存器
  • 更新调度数据

快速切换会产生并行执行的幻觉。

进程控制块 (PCB)

内核使用 PCB 来跟踪每个进程,PCB 存储:

  • 调度信息
  • 内存映射
  • 打开的文件表
  • 会计数据

虚拟内存

虚拟内存为每个进程提供了独立的地址空间。页表将虚拟地址映射到物理内存,内核通过这些映射执行保护规则。

文件描述符

文件描述符将进程与资源关联。每个描述符指向内核表项,该表项引用文件、设备或管道。内核管理权限和引用计数。

Source:

观察进程

你可以通过常用命令看到这些概念的实际运行情况。

ps aux

显示当前活动进程的快照,每一行代表一个由内核跟踪的进程,并列出 CPU 和内存使用情况。

top

提供实时、持续更新的视图。你可以观察进程在调度器轮转任务时状态的变化。

尝试一下:

  1. 在一个终端中启动一个长时间运行的程序。
  2. 在另一个终端中使用 pstop 观察它。
  3. 停止该程序,观察它的条目消失。

每个你运行的程序都会触发进程创建、调度和资源跟踪,这些步骤在后台不断循环进行,决定了系统的行为方式。

下次在终端中按 Enter 时,记住你正在启动一个完整的进程生命周期,且全程由你控制。

0 浏览
Back to Blog

相关文章

阅读更多 »

Python内部:装饰器

不要把 @ 符号当作魔法。让我们拆除抽象层,从第一原理构建 decorators,使用 heap allocation、closures……