Linux 进程同步以及僵尸进程等知识介绍
Linux 进程与线程核心知识总结
本文整理了嵌入式 Linux 软件开发面试中关于进程与线程的高频考点及知识要点,涵盖进程模型、通信方式、IO 模型、内存布局、进程状态等内容,适合查漏补缺或面试前快速复习。
1. 异步 IO 与同步 IO
概念对比
类型 | 行为描述 |
---|---|
同步 IO | 线程发起 IO 请求后必须等待操作完成,才能继续执行后续代码。 |
异步 IO | 线程发起 IO 请求后立即返回,可继续处理其他任务,IO 在后台完成后内核会通知或回调线程。 |
直观理解
- 同步:“我等你” —— 线程发起读写请求后阻塞,直到 IO 完成。
- 异步:“我先忙别的,你好了通知我” —— 提高系统并发能力和 IO 吞吐量。
示例:异步网络服务器(如 Nginx)通常使用 epoll + 异步 IO 提高性能;同步 IO 常见于简单文件读写。
2. 进程间通信(IPC)方式
Linux 提供了多种进程间通信机制,各具特点:
方式 | 特点与场景 |
---|---|
管道(Pipe) | 是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程之间使用,通常是父子进程。 |
有名管道(FIFO) | 也是半双工的通信方式,但是它允许用于无亲缘关系的进程之间的通信。 |
信号量(Semaphore) | 是一个计数器,通常作为一种同步机制,用于进程和线程间的同步。 |
消息队列(Message Queue) | 是一个消息链表,存放在内核中并且由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限的缺点。 |
共享内存(Shared Memory) | 一段能够被多个进程共同访问的内存,由一个进程创建。共享内存是最快的IPC方式,它是针对其他进程间通信方式运行效率低而设计的,往往与其他通信方式如信号量配合使用,来实现进程间同步与通信。 |
套接字(Socket) | 可用于不同主机间的进程通信。 |
信号(Signal) | 用于通知接收进程某个事件已经发生,是一种比较复杂的通信方式。 |
选择建议
- 大数据高性能:共享内存 + 信号量
- 简单父子通信:管道
- 跨机器:Socket
- 异步解耦:消息队列
3. 进程的地址空间模型
Linux 进程的内存布局通常如下(低地址 → 高地址):
┌───────────────────────────┐ 高地址
│ Kernel Space (内核空间) │ 仅内核访问
├───────────────────────────┤
│ Stack (栈) │ 局部变量、函数参数,向下增长
├───────────────────────────┤
│ Memory Mapping Area │ mmap 映射区,动态库、文件映射、匿名大块分配
├───────────────────────────┤
│ Heap (堆) │ malloc/new 分配,向上增长
├───────────────────────────┤
│ BSS Segment │ 未初始化或初始化为 0 的全局/静态变量
├───────────────────────────┤
│ Data Segment │ 已初始化的全局/静态变量、const 常量
├───────────────────────────┤
│ Text Segment │ 程序代码(只读,可共享)
└───────────────────────────┘ 低地址
要点
- Text:可共享,通常只读,存放可执行指令。
- Data/BSS:分别存放初始化和未初始化的全局/静态变量。
- Heap:动态分配的内存区域,手动申请与释放。
- Stack:函数调用帧、局部变量,自动分配与释放。
- Memory Mapping:
mmap
文件映射或大块内存分配。
4. 进程的五种状态
Linux 内核为每个进程维护一个状态机,典型状态如下:
状态 | 描述 |
---|---|
就绪态 | 进程已具备运行条件,等待 CPU 调度。 |
运行态 | 正在 CPU 上执行。 |
等待态 | 分为可中断睡眠(浅度睡眠)与不可中断睡眠(深度睡眠),等待资源或事件。 |
暂停态 | 收到 SIGSTOP 或 SIGTSTP 等信号,暂时停止调度,可通过 SIGCONT 恢复。 |
僵尸态 | 子进程已结束但父进程尚未回收(未 wait() ),仅保留少量进程表信息。 |
通过
ps -elf
或top
查看,STAT
字段中:
R
运行态S
睡眠态T
暂停态Z
僵尸态
5. 孤儿进程与僵尸进程
对比项 | 孤儿进程 | 僵尸进程 |
---|---|---|
形成条件 | 父进程先退出,子进程继续运行 | 子进程退出,父进程未 wait() |
资源占用 | 占用正常运行资源 | 仅占用 PID 和少量内核表项 |
系统影响 | 一般无害,init/systemd 会收养并回收 | 若父进程不回收,大量僵尸会耗尽 PID,导致无法创建新进程 |
处理方式 | 无需特殊处理 | 修正父进程调用 wait() ;或终止父进程让 init 接管 |
总结
- 异步 IO 提升并发性能;同步 IO 实现简单。
- IPC 方式各有适用场景,需根据数据量、延迟要求、进程关系选择。
- 进程地址空间体现了程序运行时的内存组织,是理解内存管理和调优的基础。
- 进程状态和孤儿/僵尸进程是排查系统问题的常见切入点。
熟悉这些核心概念,不仅能应对嵌入式 Linux 开发面试,更有助于日常调试与性能优化。