前言
进程是操作系统的核心骨架,所有程序的运行本质都是进程的调度与执行。理解进程的底层逻辑,不仅能打通操作系统、硬件与应用程序的关联,更能为排查性能问题、编写高效代码打下基础。
本文将从冯诺依曼体系结构出发,逐步拆解操作系统的核心职责,再深入进程的定义、PCB 结构、状态转换、优先级调度等核心知识点,同时搭配 ps/top/fork 等实操指令与代码示例,兼顾理论深度与实战性。无论是刚接触 Linux 系统的初学者,还是想夯实底层基础的开发者,都能通过本文理清进程的完整逻辑链,掌握从'认识进程'到'操控进程'的核心能力。
冯诺依曼体系结构
这里指的存储器是内存,是硬件级别的缓存空间(外存不算在这里)。 外设分为输入设备和输出设备。 输入设备:鼠标,键盘,磁盘,网卡… 输出设备:显示器,播放器硬件,磁盘,网卡。 由此看出:有些设备既有输入功能,又有输出功能。 中央处理器 (CPU):由运算器和控制器组成。 运算器:对数据进行计算任务(算数运算,逻辑运算等)。 控制器:对计算硬件流程进行一定的控制。 他们都是独立的个体! 不考虑缓存情况的话,这个中央处理器是不会跟输入输出设备直接联系的,都是通过存储器进行联系的。这样设计的好处:提高 CPU 的工作效率(不用等输入输出设备慢慢输,可以趁这个时间搞其他的)。 一个程序要运行,就必须先加载到内存中运行的原因:冯诺依曼体系结构的规定。
操作系统
概念:操作系统是一款进行管理的软件(可以管理软件和硬件)。 要管理这么多东西–注定了操作系统里面存在大量的数据结构(因为先描述再组织)。 为什么要有操作系统:
- 可以帮助用户管理好下面的软硬件资源。
- 为用户提供一个良好(也就是稳定,高效,安全)的运行环境。 也就是操作系统通过管理好底层的软硬件资源(手段),为用户提供一个良好的执行环境(目的)。 操作系统里面由大量的数据,但是不想被用户获取。所以:为了保证自己的数据安全,也为了能够给用户提供服务,操作系统以接口的方式给用户提供调用的入口,来使用操作系统内部的数据。 这个接口是操作系统自己提供的,用 C 语言实现的,像这种操作系统自己内部进行的函数调用,称为系统调用。 –所有访问操作系统的行为,都只能通过系统调用来完成。 操作系统管理数据的方法–先描述再组织(6 个字很重要)。 (也就是先描述数据属性,再把数据串起来)。 在操作系统中,管理任何对象,最终都可以转化成对某种数据结构的增删查改。 库函数和系统调用: 库函数是通过系统调用提供的接口实现的。 这俩个在写代码的时候都可以用(但是要编程语言支持这个)。
进程的概念
一个加载到内存中的程序(也就是正在运行的程序),叫做进程–这个说法不准确哈。 进程 = 内核 PCB 数据结构对象 + 代码和数据。 (代码和数据一直在,只有在运行的时候才会产生 PCB)。 PCB(进程控制块):进程属性的集合,描述了这个进程的所有属性。 在 Linux 内核里,进程有时候也叫做任务。 大多数 Linux 的指令都是 bash 的子进程。 一个操作系统不仅仅只能运行一个进程,可以同时运行多个进程。 任何一个'进程'在加载到内存形成真正的进程时,操作系统会先创建描述进程的结构体对象–也就是 PCB。 对进程做管理其实也就是对 PCB 做管理。 '进程的执行有先后'其实是 PCB 在排队等执行,而不是代码和数据。 具体到 Linux 是怎么处理进程的:
- pcb 在其中是 task_struct 结构体,里面包含进程的所有属性(先描述)。 (也就是在 Linux 中描述进程的结构体叫做 task_struct)。
- Linux 中组织进程:用双向链表组织。 如何通过链表节点(令为 start)反向定位 task_struct,从而访问其他 PCB 的数据: 比如 task_struct 里面跟 start 同位置的是 link。 那么定位 start 的 task_struct 的方法: task_struct 内容分类 标示符:描述本进程的唯一标示符,用来区别其他进程。 状态:任务状态,退出代码,退出信号等。 优先级:相对于其他进程的优先级。 程序计数器 (也叫做 PC 指针):程序中即将被执行的下一条指令的地址。 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。 上下文数据:进程执行时处理器的寄存器中的数据。 I/O 状态信息:包括显示的 I/O 请求,分配给进程的 I/O 设备和被进程使用的文件列表。 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。 其他信息 所有指令的运行都是进程。
查看进程
引申:1.如果想要干掉一个进程的话,可以 kill -9 PID 值(ctrl+c 干不掉时用此可以试试)。
/proc 方法
语法:ls /proc 查看当前所有的进程信息。
ps 指令
语法:ps ajx | head -1 就是查看系统中进程的状态信息(只用第一行,所以 -1)。 PPID 是当前进程的父进程的 ID 值 --PPID 一般不变,在同一终端下的话。 PID 是进程的 ID 值(是唯一的),如果进程结束,再重新开始,PID 大概率会变。 –PID 值也是个目录其实。 COMMAND 是进程对应的'命令名称或启动路径'。 语法:ps ajx | grep 文件名 可以查询这个文件对应的这些信息。 ps 一般这样用:ps ajx | head -1 ; ps ajx | grep 文件名。
通过系统调用获取进程标示符
比如:getpid 和 getppid 这俩个系统调用接口(具体的用 man 指令去查)。


