一.进程的基本概念

进程描述是一个程序执行过程。当程序执行后,执行过程开始,则进程产生;执行过程结束,则进程也就结束。

下面是 windows 系统中,所有的进程,即正在执行的程序,一旦结束进程,就意味着程序结束

可能这个例子暂且可以说明进程到底是什么,但是还是不够形象生动。

那么我再举一个例子:要理解 “进程”,最生动的类比就是餐厅的 “顾客点餐 - 制作” 流程—— 进程本质是 “操作系统中正在执行的程序实例”,就像餐厅里 “正在被服务的顾客订单”,每个订单都独立占用资源、有自己的执行步骤,互不干扰。

二.进程的特点

1. 动态性:进程是 “活” 的,有完整生命周期

进程不是静态的程序,而是程序的 “执行过程”,从创建到终止会经历一系列状态变化(创建→就绪→运行→阻塞→终止),就像 “餐厅订单” 从下单到上菜的完整流程:

  • 刚下单时(创建)→ 等厨师有空(就绪)→ 厨师正在做(运行)→ 缺食材暂停(阻塞)→ 做好上桌(终止)。这种动态性是进程与 “静态程序”(如硬盘里的.exe 文件、餐厅菜单)最根本的区别。

2. 独立性:每个进程都是 “独立王国”,互不干扰

每个进程拥有独立的内存空间、资源集合,操作系统通过 “进程隔离” 机制确保它们互不干扰:

  • 比如你同时开着微信和浏览器,微信的内存数据(聊天记录)和浏览器的内存数据(网页缓存)完全分开,即使微信崩溃(进程异常终止),浏览器也能正常运行,就像 “1 号桌订单出错不会影响 2 号桌的菜”。这种独立性是系统稳定运行的基础 —— 单个进程的故障不会 “拖垮” 整个系统。

3. 并发性:多个进程 “同时” 存在,CPU 轮流服务

在单 CPU(或单厨师)场景下,多个进程能通过 CPU 的 “时间片调度” 实现 “并发执行”:

  • 比如 CPU 给微信 10 毫秒处理消息,再给浏览器 10 毫秒加载网页,切换速度极快(毫秒级),用户感觉不到卡顿,就像 “厨师交替炒两桌的菜,两桌顾客都觉得自己的菜在被优先处理”。并发性是操作系统 “同时运行多个程序” 的核心实现方式(注意:并发≠并行,并行需要多个 CPU 核心真正同时处理)。

4. 结构性:每个进程都有 “身份档案”(PCB)

操作系统为每个进程维护一个进程控制块(PCB),相当于进程的 “身份证 + 资源清单”,记录关键信息:

  • 进程 ID(唯一标识,如 “1 号桌”)、状态(运行 / 阻塞等)、占用的内存地址、CPU 使用记录、打开的文件列表等。PCB 是操作系统管理进程的 “依据”—— 通过查询 PCB,系统能快速知道 “哪个进程在等资源”“哪个进程该分配 CPU 时间”。

5. 资源独占性:运行时 “占用专属资源”,用完释放

进程在执行过程中会独占一定的系统资源(内存、CPU 时间片、磁盘文件句柄等),直到进程终止才释放:

  • 比如微信运行时会占用一块内存存聊天窗口数据,关闭微信后,这块内存会被操作系统回收,就像 “1 号桌的菜做完后,炒锅、餐盘会被清理出来给其他桌用”。资源独占性确保了进程能 “不受干扰地完成任务”,避免多个进程争抢资源导致的混乱。

总结来说,进程是一个独立的可调度的活动,由操作系统进行统一调度,相应的任务会被调度到 cpu 中进行执行。进程一旦产生,则需要分配相关资源,同时进程是资源分配的最小单位。

进程的这些特点共同支撑了操作系统的 “多任务处理能力”—— 让电脑能同时运行微信、浏览器、音乐软件,就像餐厅能同时服务多桌顾客、教务处能同时处理多个申请,既高效又有序。

三.进程与程序之间的关系

说了这莫多,大家有没有发现进程和程序之间有着千丝万缕的联系,那么他们之间到底有什么区别需要大家去注意呢?

可以用 “剧本与演出” 的关系来类比:程序是静态的 “剧本”,进程是动态的 “演出过程”—— 剧本(程序)是演出(进程)的基础,而演出(进程)是剧本(程序)的具体执行。

一、核心联系:进程依赖程序存在

  1. 程序是进程的 “物质基础”进程本质是 “程序的执行过程”,没有程序就没有进程。就像 “没有剧本,就无法进行演出”:

    • 程序保存在硬盘上的静态指令集合(如wechat.exepython test.py的代码),规定了 “要做什么、怎么做”;
    • 进程是这些指令被加载到内存后,由 CPU 执行的动态过程 —— 没有程序的指令,进程就成了 “无米之炊”。
  2. 一个程序可以对应多个进程同一程序(剧本)可以被多次执行,产生多个独立的进程(多场演出):

    • 比如你双击两次 “微信” 图标,会打开两个微信窗口 —— 这是两个独立的 “微信进程”,但它们依赖的是同一个wechat.exe程序;
    • 就像同一部《哈姆雷特》剧本,伦敦剧院和纽约剧院可以同时上演(两个 “演出进程”),共用同一个剧本(程序)。
  3. 一句话总结

    程序是 “死” 的指令集合,进程是 “活” 的执行过程—— 程序是进程的 “蓝本”,进程是程序的 “实例化运行”。没有程序,进程无从谈起;而程序若不被执行(即不成为进程),就只是一堆毫无意义的二进制数据。

四.并发与并行

并行执行 : 表示多个任务能够同时执行,依赖于物理的支持,比如 cpu 8 核芯,则可以同时执行 8 个 任务
并发执行 : 同一时间段有多个任务在同时执行,由操作系统调度算法来实现,比较典型的就是时间片轮转

理解 “并发” 与 “并行” 的核心区别,关键看 “同一时刻是否真的在同时做多个任务”—— 并发是 “同一时间段内交替推进多个任务”,像 “单线程切换”;并行是 “同一时刻同时推进多个任务”,像 “多线程同步”。用两个生活中最直观的场景就能讲透:

一、并发(Concurrency):“一个人,交替干多个活”

核心特点:同一时间段内多个任务都在推进,但同一时刻只干一件事(靠 “时间片交替” 实现,给人 “同时做” 的错觉)。

形象例子:1 个厨师,同时做 “煮米饭” 和 “炒青菜”

假设你只有 1 个厨师,要同时搞定 “煮米饭” 和 “炒青菜” 两个任务,过程是这样的:

  1. 厨师先把米洗好放进锅里,加水开火(启动 “煮米饭” 任务)—— 但煮米饭需要等 15 分钟水开、再焖 10 分钟,中间有大量 “等待时间”;
  2. 不等米饭煮好,厨师转身去切青菜、热锅倒油(切换到 “炒青菜” 任务),翻炒 3 分钟把青菜炒好装盘;
  3. 此时回头看米饭,发现水刚开,厨师调小火焖煮(给 “煮米饭” 任务续上进度);
  4. 焖米饭的间隙,厨师又去收拾灶台(顺便处理其他小任务),直到米饭焖好。

整个过程中,1 个厨师(对应 1 个 CPU 核心)在 “煮米饭” 和 “炒青菜” 之间交替切换,没有任何一个任务被完全搁置,15 分钟内两个任务都完成了 —— 这就是并发。

电脑中的对应场景:单 CPU 电脑同时聊微信和刷网页
  • 你的电脑只有 1 个 CPU 核心,却能同时开着微信(收消息)和浏览器(刷csdn);
  • 本质是 CPU 在 “微信进程” 和 “浏览器进程” 之间快速切换:先给微信分配 10 毫秒(处理刚收到的消息),再给浏览器分配 10 毫秒(加载网页图片),切换速度快到毫秒级,你完全感觉不到 “卡顿”,误以为两个任务在 “同时跑”—— 这就是 CPU 的并发调度。

二、并行(Parallelism):“多个人,同时干多个活”

核心特点:同一时刻,多个人 / 资源在同时推进不同任务(没有交替,是 “物理上的真同时”,效率更高)。

形象例子:2 个厨师,同时做 “煮米饭” 和 “炒青菜”

还是这两个任务,但现在有 2 个厨师(厨师 A 和厨师 B):

  1. 厨师 A 专门负责 “煮米饭”:洗米、加水、开火,全程盯着米饭的火候,不需要切换任务;
  2. 厨师 B 专门负责 “炒青菜”:切菜、热锅、翻炒,3 分钟就能把青菜做好;
  3. 最终,炒青菜 3 分钟完成,米饭 15 分钟完成 —— 两个任务从 “开始到推进” 的每一个时刻,都有专人在处理,没有任何交替等待。

整个过程中,2 个厨师(对应 2 个 CPU 核心)在同一时刻分别干不同的活,两个任务完全 “并行推进”—— 这就是并行。

电脑中的对应场景:双核 CPU 电脑同时开微信和剪视频
  • 你的电脑是双核 CPU(两个独立核心),此时你开着微信(收消息),同时用剪映剪视频;
  • CPU 核心 1 会专门负责 “微信进程”(处理消息接收、界面渲染),核心 2 专门负责 “剪映进程”(处理视频剪辑、导出计算);
  • 两个核心在同一时刻各自执行自己的任务,没有交替切换,剪视频的速度不会因为聊微信而变慢 —— 这就是 CPU 的并行处理。

一句话总结:

并发是 “一个人交替假装同时干多活”,并行是 “多个人真的同时干多活”—— 前者靠 “时间片切换” 提升单资源利用率,后者靠 “多资源同步” 提升整体效率。

五、Linux 进程管理

1. Linux 系统中,管理进程使用树型管理方式。
2. 每个进程都需要与其它某一个进程建立父子关系,对应的进程叫做父进程。
3. Linux 系统会为每个进程分配id ,这个id作为当前进程的唯一标识,当进程结束,则会被回收
4. 进程的id与父进程的id分别通过getpid()与getppid()来获取
函数头文件: #include <sys/types.h> #include <unistd.h>
函数原型
pid_t getpid(void);
pid_t getppid(void);
函数功能:获取当前进程id与父进程id
函数返回值 :成功:getpid() 返回当前进程id,getppid()返回父进程id
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    printf("Hello multiprocessing!\n");
    printf("pid:%d,ppid=%d\n",getpid(),getppid());
    return 0;
}
Hello multiprocessing!
pid:2818,ppid=2489

到这相信大家对进程有了一定的了解,下个阶段我们要更深层次的学习进程!

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐