Linux学习-多任务(进程)
多任务:让系统具备同时处理多个任务的能力
1.多线程
2.多进程
3.进程间通信
进程
进程是正在运行的程序,运行时需消耗内存与 CPU 资源,是程序动态执行的过程,有从产生、调度到消亡的生命周期 。
程序与进程的区别
程序:静态数据集合,存储于硬盘。 程序运行产生进程;一个程序可生成多个进程 。
进程:程序动态执行过程,消耗内存、CPU 。一个进程中可执行多个程序 。具备动态生存周期,从产生到调度再到消亡。
进程的产生
进程产生时,操作系统会为其分配 0 - 4G 的虚拟内存空间 ,作为进程运行的 “容器” ,承载后续各类数据与代码的存储、执行 。
(一)内核区(3G - 4G )
属于操作系统内核使用区域,承担文件管理、进程管理、内存管理等核心功能,是系统稳定运行的基础支撑 。
(二)栈区(靠近 3G )
- 存储内容:局部变量、函数形参和返回值,以及函数调用关系(用于保护现场、恢复现场,保障函数调用流程有序) 。
- 特点:由系统自动分配和释放,遵循 “后进先出” 原则,空间管理高效 。
(三)堆区(介于栈区与数据区之间 )
- 分配释放:由开发人员手动分配(如 C 语言中 malloc 函数 )、手动释放(如 free 函数 ) 。
- 作用:为程序动态分配内存,满足运行时按需申请空间的需求,若未正确释放易引发内存泄漏问题 。
(四)数据区
1. data 段:存储已初始化的全局变量、已初始化的静态变量( static 修饰 ),程序启动时就有确定初始值 。
2. bss 段:存放未初始化的全局变量、未初始化的静态变量( static 修饰 ),初始时会被系统按位清 0 ,程序运行中可赋值使用 。
3. 字符串常量区:保存字符串常量(如 "hello world" ),为字符串提供统一存储,避免重复定义占用空间 。
(五)文本区(靠近 0 地址 )
存储内容:指令代码(程序要执行的操作逻辑 )、字符 / 数值常量(如 'A' 、 10 、 0xAA 等 )
进程的调度
CPU 数据处理速度快,呈现 宏观并行、微观串行 特点。
即从用户视角,多个进程似同时运行(宏观并行 );
实际 CPU 微观上按序处理进程任务(微观串行 )。
CPU调度算法:
1.时间片轮询算法
2.先来先服务(任务队列) 按进程到达顺序,先到先执行,遵循队列规则
3.短作业优先调度 优先调度执行时间短的作业,提升整体效率
4.优先级调度 高优先级进程先执行,低优先级后执行,适配重要任务
进程的状态
操作系统进程的三态图:
Linux操作系统的进程图:
运行态(R):包含用户运行态、内核运行态,是正在被 CPU 任务调度执行的进程状态。
就绪态(R): 进程具备执行条件,仅缺少 CPU 调度,等待获取 CPU 资源即可执行。
可唤醒等待态(S):又称睡眠态,进程因阻塞等待资源(如 I/O 资源等 )而暂停,当等待的资源可用时可被唤醒。
不可唤醒等待态(D):用于不想被 CPU 调度打断的进程任务,在等待特定条件时,不受调度干扰,保障关键流程连续性。
暂停态(T):进程被暂停执行,需外部操作(如调试指令 )恢复运行。
僵尸态(Z):进程执行结束,但占用的资源空间未被系统回收,残留相关信息,需父进程或系统处理清理。
结束态(X):进程执行完毕,且资源空间已被系统回收,彻底终止,无残留资源。
进程的消亡
1.进程执行结束(进程退出)
2.回收进程资源空间
进程相关命令
- PID:进程唯一 ID 号,标识单个进程。
- PPID:父进程 ID 号,表明进程的父级来源。
- 父进程:产生子进程的进程;
-子进程:父进程创建的新进程,体现进程间的父子关系。
基本命令
(一) ps 系列
- ps -aux :查看进程参数(PID、状态、CPU/内存占有率 ),全面获取进程运行数据。
- ps -aux | grep /a.out :结合管道( | ,前命令输出为后命令输入 )与 grep (字符串查找 ),精准筛选含 /a.out 的进程信息。
(二) top
动态监控进程,实时查看 CPU 占有率、内存占有率等,便于观察进程资源变化。
(三) ps -ef
聚焦进程 ID(PID )与父进程 ID(PPID ),清晰呈现进程父子关系。
(四) pstree 系列
- pstree :展示进程树状产生关系,直观呈现进程层级。
- pstree -p :带 PID 显示进程树,补充进程唯一标识。
- pstree -sp 进程PID :指定进程 PID,精准查询该进程的父子关系链。
(五) kill 系列
- kill -信号编号/名称 PID :向进程发信号,改变进程状态(如终止、暂停 )。
- kill -l :查看系统支持的信号列表,了解可用控制指令。
- kill -9 PID :强制终止进程( -9 为强制终止信号 ),快速结束指定进程。
jobs:查看当前终端的后台进程
fg 编号:让一个后台进程进入前台
进程相关编程
进程创建
- fork() :通过拷贝父进程创建子进程,子进程拷贝父进程 0 - 3G 虚拟内存空间、部分 PCB(进程控制块,PID 不拷贝 )。
- getpid() :获取当前进程自身 PID 号 。
- getppid() :获取当前进程父进程的 PID 号 。
fork()函数:
- 功能:拷贝父进程生成新子进程,子进程完全复制父进程 0 - 3G 虚拟内存(栈、堆、数据区、文本区等 ),但 PID 独立 。
- 返回值:父进程返回子进程 PID( >0 );子进程返回 0 ;出错返回 -1 。
- 注意:父子进程栈、数据区等完全独立,数据不共享,需进程间通信实现数据交互 。
进程调度
由操作系统自动完成,负责分配 CPU 资源,决定进程执行顺序与时长,保障系统高效、有序运行
进程消亡
进程退出
1. main 函数中 return :在程序入口函数 main 里执行 return ,可结束进程,常搭配返回值体现退出状态(如 return 0 表正常, return 非0 表异常 )。
2. exit() 与 _exit() :
二者均可主动终止进程, exit(0) 代表正常退出, exit(非0) 用于进程因问题主动退出场景。
区别: exit() 会执行一些收尾操作(如刷新 I/O 缓冲区 ), _exit() 直接终止,更 “暴力”。
资源回收
wait() / waitpid() :父进程调用,用于回收子进程资源,避免子进程成为僵尸进程(进程退出但资源未回收 )。
僵尸进程:子进程退出后,父进程未及时回收其资源,进程残留 “躯壳”(PCB 等未释放 )。
避免方法:
1.子进程退出后,父进程用 wait() / waitpid() 及时回收。
2.让子进程成为孤儿进程,由系统进程(如 init 进程 )回收。
孤儿进程:父进程先消亡,子进程被系统进程(守护类进程 )收养,结束时由系统回收资源,是一种 “被动” 避免僵尸进程的方式。