1.进程线程和协程
1.1 垂直包含关系
进程(容器层) → 线程(执行层) → 协程(任务层)
- 进程 是资源分配的顶层单位,为程序提供独立的内存、文件等隔离环境;是操作系统中进行资源分配和调度的基本单位。
- 每个进程至少包含 1个主线程。
- 示例:浏览器中每个标签页是独立进程,崩溃互不影响。
- 线程 是CPU调度的基本单位,共享进程内的资源(内存、文件等);它是进程内的一个执行单元,也是CPU调度和分配的基本单位。
- 1个进程可包含 多个线程(如Chrome的渲染线程、网络线程)。
- 示例:视频编辑软件用多线程并行处理不同轨道的渲染。
- 协程 是用户态轻量级线程,寄生在线程中,由程序自行调度;其调度完全由用户程序控制,而不需要内核的参与。
- 1个线程可调度 成千上万个协程(如Go的goroutine)。
- 示例:Web服务器用协程同时处理数万个HTTP连接。
类比:
- 进程 = 工厂(独立厂房和原料仓库)
- 线程 = 生产线(共享厂房,多条线并行)
- 协程 = 工人(在一条生产线上快速切换任务)
1.2 协作场景示例(Web服务器架构)
1
2
3
4
5
6
7
8
[主进程](守护进程)
│
┌───────┴───────┐
[子进程A] [子进程B] ← 隔离用户A/B会话
│ │
[线程池] [线程池] ← 每个进程4线程(4核CPU)
│ │
[协程群] [协程群] ← 每线程处理1万个连接
- 进程级隔离:防止单个用户请求崩溃导致服务全局瘫痪。
- 线程级并行:利用多核CPU执行压缩/加密等计算任务。
- 协程级并发:用极低开销管理海量I/O操作(如数据库查询)。
1.3 三者的本质区别
| 维度 | 进程 | 线程 | 协程 |
|---|---|---|---|
| 资源 | 独立内存/文件 | 共享进程内存 | 共享线程栈 |
| 切换 | 需内核介入(开销大) | 需内核介入(开销中) | 用户态切换(开销极小) |
| 崩溃 | 不影响其他进程 | 可能导致进程崩溃 | 仅影响当前协程 |
关键结论:
- 包含性:进程 ⊃ 线程 ⊃ 协程
- 协作性:三者共同实现 安全隔离(进程)、硬件利用(线程)、高并发(协程)。
1.4 线程切换、
1.5 进程状态、上下文、通讯和调度
1.6 其他问题
2.Lunix常用命令合集
Lunix如何查看进程号状态?
1
2
3
4
5
6
7
8
# a:显示所有用户的进程。
# u:展示详细的用户信息。
# x:显示没有控制终端的进程。
# -e:等同于a,即显示所有进程。
# -f:呈现完整格式的输出。
ps aux # 显示所有用户的所有进程
ps -ef # 显示完整格式的进程信息
ps -ef | grep 进程名 # 查找特定进程
Lunix下如何查看网络连接情况?
1
2
3
4
5
# netstat:查看网络连接情况
netstat -anp # 显示所有网络连接
netstat -tnp # 显示tcp连接
netstat -tnlp # 显示tcp连接和监听端口
netstat -s # 显示网络统计信息
Lunix下如何查看磁盘使用情况?
1
2
# df:查看磁盘使用情况
df -h # 以可读方式显示磁盘使用情况
Lunix下如何查看内存使用情况?
1
2
# free:查看内存使用情况
free -h # 以可读方式显示内存使用情况
Lunix下如何查看CPU使用情况?
1
2
# top:查看CPU使用情况
top # 按1、5、15分钟的平均负载显示CPU使用情况
Lunix下如何查看进程的内存使用情况?
1
2
# pmap:查看进程的内存使用情况
pmap -x 进程号 # 查看进程的内存使用情况
Lunix下如何查看进程的CPU使用情况?
1
2
# pidstat:查看进程的CPU使用情况
pidstat -u 1 # 显示每秒的CPU使用情况
Lunix下如何查看进程的IO使用情况?
1
2
3
# iostat:查看进程的IO使用情况
iostat -d 1 # 显示每秒的磁盘IO使用情况
iostat -x 1 # 显示每秒的磁盘IO使用情况,包括系统调用
Lunix下如何查看进程的网络使用情况?
1
2
# iftop:查看进程的网络使用情况
iftop -t # 显示每秒的网络IO使用情况
Lunix下如何查看进程的线程数?
1
2
# pstree:查看进程的线程数
pstree -p 进程号 # 查看进程的线程数
3.操作系统的内存管理
3.1 虚拟内存
操作系统设计了虚拟内存,每个进程都有自己的独立虚拟内存,我们写的程序不会直接与物理内存打交道;虚拟内存是操作系统提供给每个运行中程序的一种地址空间,每个程序在运行时认为自己拥有的内存空间就是虚拟内存。
虚拟内存通过将程序的地址空间划分为若干个固定大小的页或段,并将这些页或段映射到物理内存中的不同位置,从而使得程序在运行时可以更高效的利用物理内存。
虚拟内存带来的好处:
- 可以使得进程得运行内存超过物理内存大小;
- 进程的虚拟空间相互独立,解决了多进程之间地址冲突的问题;
- 页表的页表项中除了物理地址外,还有一些标记属性的比特(控制一个页的读写权限,标记该页是否存在),提供了更好的安全性;
Linux是通过对内存分页的方式来管理内存,分页是把整个虚拟和物理内存空间切成一段段固定尺寸的大小。这样一个连续且尺寸固定的内存空间叫做页(page)。在Linux下,每一页的大小为4kB。虚拟地址与物理地址之间通过页表进行映射。

MMU 内存管理单元
内存管理单元(MMU)的工作是将虚拟内存地址转化为物理地址;
缺页异常:CPU访问的虚拟内存地址时,MMU没有办法找到对应的物理地址映射关系,会产生一个缺页异常,此时CPU会暂停当前进程,并进入系统内核空间分配物理内存、更新进程页表,最后再返回用户空间,恢复进程的运行。
为什么虚拟内存可以超过物理内存?
- 地址转换:虚拟地址空间独立于物理内存大小;
- 分页与交换:仅活跃页面占用物理内存,其余暂存磁盘;
- 按需加载:程序启动时无需加载全部代码和数据,减少初始内存占用;
- 共享内存:多个进程可共享同一物理页面(如库文件),减少重复占用。 参考连接:虚拟内存管理
对于一个内存地址转换,总结为以下三个步骤:
- 把虚拟内存地址,切分成页号和偏移量;
- 根据页号,从业表里面,查询对应的物理页号;
- 直接拿物理页号,加上前面的偏移量,就得到了物理内存地址;
段表: 虚拟地址也可以通过段表与物理地址进行映射。
分段机制会把程序的虚拟地址分成 4 个段,每个段在段表中有一个项,在这一项找到段的基地址,再加上偏移量,于是就能找到物理内存中的地址,如下图:

段表
3.2 程序的内存布局

程序内存布局