一、进程的核心定义
1.1 基本概念
进程是操作系统进行资源分配和调度的基本单位,是一个正在执行的程序实例。它不仅包含程序代码,还包括执行该程序所需的所有系统资源状态。
1.2 经典定义对比
| 程序角度 | 程序的一次执行过程 | 动态 vs 静态 |
| 资源角度 | 拥有独立资源的基本单位 | 隔离性、保护性 |
| 系统角度 | 操作系统调度的实体 | 并发性、状态性 |
一个程序可对应多个进程,一个进程只能执行一个程序。
具体区别:
| 存在形式 | 静态文件(.exe, .dll) | 动态执行实体 |
| 生命周期 | 永久存储 | 创建→运行→终止 |
| 资源占用 | 仅磁盘空间 | CPU、内存、I/O等 |
| 并发性 | 无 | 可并发执行 |
| 状态 | 无状态概念 | 就绪、运行、阻塞等 |
二、进程与线程的区别
| 资源拥有 | 资源的所有者 | 资源的使用者 |
| 地址空间 | 独立虚拟地址空间 | 共享进程地址空间 |
| 通信成本 | 高(需要IPC) | 低(直接共享内存) |
| 创建开销 | 大(需分配资源) | 小(共享资源) |
| 健壮性 | 一个进程崩溃不影响其他进程 | 一个线程崩溃可能导致整个进程崩溃 |
| 安全性 | 高(有内存保护) | 较低(可互相访问) |
三、Windows进程的架构
3.1 进程作为内核对象
在Windows中,进程本身是一个内核对象(类型为Process):
// 进程内核对象的结构(简化概念)
typedef struct _EPROCESS { // Executive Process Block
KPROCESS Pcb; // 内核进程控制块
HANDLE UniqueProcessId; // 进程ID (PID)
HANDLE InheritedFromUniqueProcessId; // 父进程ID
LIST_ENTRY ActiveProcessLinks; // 活动进程链表
PVOID SectionBaseAddress; // 映像基地址
// … 其他字段(超过60个)
} EPROCESS;
3.2 进程的组成要素
一个完整的Windows进程包含:
3.2.1 虚拟地址空间
3.2.2 核心数据结构
// 进程的关键组件
struct PROCESS_COMPONENTS {
EPROCESS* eprocess; // 内核进程块
PEB* peb; // 进程环境块(用户态)
HANDLE_TABLE* handle_table; // 句柄表
VM_SPACE* address_space; // 虚拟内存管理器
TOKEN* access_token; // 安全访问令牌
JOB* job; // 可能的作业对象
LIST thread_list; // 线程列表
LIST loaded_modules; // 已加载模块(DLL)
};
3.2.3 进程环境块(PEB)
PEB位于用户地址空间,包含用户态信息:
typedef struct _PEB {
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged; // 正在被调试?
HANDLE ProcessHeap; // 进程堆句柄
PPEB_LDR_DATA Ldr; // 模块加载信息
PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // 进程参数
PVOID SubSystemData;
HANDLE ProcessHeap;
// … 更多字段
} PEB;
四、进程的生命周期
4.1 进程状态转换

4.2 Windows进程的完整生命周期
阶段1:创建进程
// Windows创建进程的步骤:
1. 验证可执行文件(PE格式检查)
2. 创建进程内核对象(EPROCESS)
3. 创建初始线程内核对象(ETHREAD)
4. 分配进程地址空间
5. 加载可执行映像和必要的DLL
6. 创建PEB和TEB(线程环境块)
7. 开始执行初始线程
创建进程的API调用链:
CreateProcess() [用户态API]
↓
CreateProcessInternal()
↓
NtCreateUserProcess() [系统调用]
↓
PspCreateProcess() [内核函数]
↓
创建EPROCESS、分配资源…
阶段2:进程执行
-
进程调度:实际上调度的是线程,进程是容器
-
资源管理:CPU时间片、内存、I/O等
-
异常处理:结构化异常处理(SEH)、向量化异常处理(VEH)
阶段3:进程终止
// 终止方式:
1. 主线程正常退出(Main函数返回)
2. 调用ExitProcess() 或 TerminateProcess()
3. 所有线程终止(如果设置)
4. 未处理异常导致崩溃
终止时的清理工作:
所有线程被终止
所有打开的内核对象句柄被关闭
进程对象变为有信号状态(用于WaitForSingleObject)
进程退出码被设置
进程对象本身:当所有句柄关闭后,内核才删除对象
五、Windows进程的特殊特性
5.1 进程优先级与类
// Windows进程优先级类
typedef enum _PROCESS_PRIORITY_CLASS {
IDLE_PRIORITY_CLASS = 0x00000040, // 空闲(4)
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000, // 低于正常(6)
NORMAL_PRIORITY_CLASS = 0x00000020, // 正常(8)
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000, // 高于正常(10)
HIGH_PRIORITY_CLASS = 0x00000080, // 高(13)
REALTIME_PRIORITY_CLASS = 0x00000100 // 实时(24)
} PROCESS_PRIORITY_CLASS;
// 设置进程优先级
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
5.2 作业对象(Job Objects)
Windows允许将多个进程分组到作业中统一管理:
// 创建和使用作业对象
HANDLE hJob = CreateJobObject(NULL, L"MyJob");
// 限制设置
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
info.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_PROCESS_TIME | // 限制CPU时间
JOB_OBJECT_LIMIT_WORKINGSET; // 限制工作集大小
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &info, sizeof(info));
// 将进程分配给作业
AssignProcessToJobObject(hJob, hProcess);
5.3 进程的完整性级别(Integrity Levels)
Windows Vista+引入的安全机制:
完整性级别(从低到高):
1. 不可信 (Untrusted) – 匿名进程
2. 低 (Low) – 保护模式IE
3. 中 (Medium) – 普通用户进程
4. 高 (High) – 管理员权限进程
5. 系统 (System) – 系统服务
原则:低完整性进程不能写高完整性资源
5.4 虚拟化机制(UAC虚拟化)
// 对于不支持UAC的旧程序,Windows提供虚拟化
// 对系统位置的写入被重定向到用户虚拟存储
C:\\Program Files\\OldApp → C:\\Users\\User\\AppData\\Local\\VirtualStore\\Program Files\\OldApp
六、进程间通信(IPC)
6.1 Windows IPC机制概览
| 文件映射 | 高性能,支持大数据 | 进程间共享数据 |
| 命名管道 | 支持双向通信 | 客户端/服务器通信 |
| 邮件槽 | 一对多广播 | 简单消息广播 |
| 剪贴板 | 系统全局共享 | 用户界面数据交换 |
| COM/OLE | 基于接口的通信 | 组件间通信 |
| RPC | 跨机器通信 | 分布式系统 |
| 窗口消息 | 仅Windows GUI程序 | 简单消息通知 |
| 套接字 | 跨网络和本地 | 网络通信 |
6.2 文件映射示例
// 进程A:创建共享内存
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // 使用页面文件
NULL, // 默认安全
PAGE_READWRITE, // 读写权限
0, 4096, // 高32位, 低32位大小
L"Local\\\\MySharedMem"); // 名称
LPVOID pBuf = MapViewOfFile(
hMapFile, // 映射对象句柄
FILE_MAP_ALL_ACCESS, // 访问权限
0, 0, 4096); // 偏移和大小
// 写入数据
strcpy((char*)pBuf, "Hello from Process A");
// 进程B:打开同一共享内存
HANDLE hMapFileB = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // 访问权限
FALSE, // 不继承
L"Local\\\\MySharedMem"); // 同一名称
LPVOID pBufB = MapViewOfFile(hMapFileB, …);
printf("收到: %s\\n", (char*)pBufB); // 输出: Hello from Process A




