基础概念
进程是操作系统资源分配的最小单位。
- PID: 进程唯一标识。
- 状态:
R(Running/Runnable): 正在运行或在就绪队列中。S(Interruptible Sleep): 可中断睡眠,等待某个事件。D(Uninterruptible Sleep): 不可中断睡眠,通常在等待 IO。Z(Zombie): 僵尸进程,子进程结束但父进程未回收。T(Stopped): 停止状态。
CPU
- 上下文切换 (Context Switch): CPU 保存当前进程状态并加载新进程状态的过程。
- 优先级:
nice值(-20 到 19),值越小优先级越高。 - 监控工具:
top,htop,vmstat。 - Load Average: 1/5/15 分钟内的平均负载,不应长期超过 CPU 核心数。
进程 / 线程 / 协程关系:
* **进程 (Process)**: 资源容器(地址空间、文件描述符等),进程之间默认内存隔离。
* **线程 (Thread)**: CPU 调度基本单位,同一进程内线程共享地址空间。
* **协程 (Coroutine)**: 用户态轻量执行单元,由运行时调度,不直接由内核调度。
* 关系可理解为:**进程承载线程,线程承载并运行协程**。
- 以 Go routine 为例(GMP):
G=Goroutine:待执行任务(函数、栈、状态)。M=Machine:内核线程,CPU 实际运行的是M。P=Processor:调度上下文(本地运行队列和调度资源)。- 为什么叫 GMP:Go 调度器正是围绕这三个核心对象设计,所以用首字母缩写为
G-M-P。 M和P的区别:M像“工人”(执行者),P像“工位+任务队列”(调度资源);M需要绑定P才能运行G。P的数量通常由GOMAXPROCS决定,影响可并行执行 goroutine 的上限。- 多个 goroutine 会复用到较少的内核线程上(
M:N调度),降低线程创建和切换成本。
- GMP 调度流程图:
flowchart LR
GQ["G 队列\n(大量 goroutine)"] --> P["P\nProcessor\n(本地运行队列+调度资源)"]
P --> M["M\nMachine\n(内核线程)"]
M --> CPU["CPU Core"]
CPU --> RUN["执行 goroutine"]
BLOCK["G 阻塞(如 syscall/IO)"] --> SCHED["运行时重新调度"]
SCHED --> P
- 实践理解:
- goroutine 切换主要在用户态完成,开销通常小于线程切换,但不是“零成本”。
- IO 密集场景下,goroutine 往往能以更低开销支撑高并发。
- CPU 密集场景下,并行度上限主要受
GOMAXPROCS(可并行使用的 CPU 核数)影响。
Memory
- 虚拟内存映射:
- Stack (栈): 局部变量、函数调用上下文。
- Heap (堆): 动态分配的内存 (
malloc)。 - Data/BSS: 全局变量、静态变量。
- Text (Code): 二进制指令。
- Heap (堆) 的含义:
- 这里的“堆”是进程虚拟内存中的一块区域(heap segment),用于运行时动态分配。
- 典型操作:
malloc/free、new/delete(在 Java/C# 中通常由 GC 管理回收)。 - 适合生命周期不固定、大小运行时才确定的对象,可跨函数存在。
- 与
Stack分工:Stack管函数调用和局部变量(自动管理、LIFO),Heap管动态对象(更灵活)。 - 注意:这里的内存“堆”不是数据结构里的“二叉堆(优先队列)”,只是同名。
- 关键指标:
VSS(Virtual Set Size): 虚拟耗用内存。RSS(Resident Set Size): 实际物理内存(含共享库)。PSS(Proportional Set Size): 按比例分配的物理内存(平摊共享库)。
IO
- File Descriptors: 每个进程能打开的最大文件数限制 (
ulimit -n)。 - I/O Wait: CPU 等待磁盘 IO 的时间比例,过高说明磁盘性能瓶颈或程序 IO 逻辑有问题。
- 监控工具:
iostat,iotop。
pmap
用于分析进程占用的内存详情。
# 查看详细扩展映射
pmap -x <PID>
- 作用: 定位内存泄漏,查看哪些库占用了大量内存。
- 相关链接:
IPC (进程间通信)
| 机制 | 描述 | 特点 |
|---|---|---|
| 管道 (Pipe) | 匿名管道用于父子进程,有名管道 (FIFO) 用于无关进程。 | 半双工,流式。 |
| 信号 (Signal) | 软件中断,如 SIGINT (Ctrl+C)。 | 异步,传递信息量小。 |
| 消息队列 (MQ) | 消息的链接表,存放在内核中。 | 克服了信号量小、管道无格式限制。 |
| 共享内存 | 映射一段能被其他进程访问的内存。 | 最快,但需要同步机制。 |
| 信号量 (Semaphore) | 计数器,用于控制多个进程对共享资源的访问。 | P/V 操作,用于同步。 |
| 套接字 (Socket) | 跨网络或本地的双向通信。 | 灵活性最高。 |