第 6 章 进程间通信 --- 6.8 本地过程调用(LPC)与 6.9 视窗报文(Message)
本章深入剖析 Windows/ReactOS 中两种核心进程间通信机制:LPC(本地过程调用)和视窗报文系统。
概述
进程间通信(IPC)是现代操作系统的核心功能,Windows 提供了多种 IPC 机制来满足不同场景的需求。本章重点介绍两种特殊的IPC机制:
LPC 和视窗报文的本质区别是什么?
LPC 是内核级的高性能请求-响应机制,专为系统组件间的高效通信设计;视窗报文系统则是用户态GUI应用的事件驱动核心,实现窗口间的消息传递。两者服务于不同层次,但共同构成了Windows的通信基础设施。
想象一个企业办公场景:
- LPC:部门之间的内部电话系统,快速、可靠的请求-响应交互;
- 视窗报文:办公室的公告板和内部邮件系统,异步消息传递和事件通知;
- CSRSS与应用程序通信:员工通过内部电话向IT部门(CSRSS)请求服务;
- 窗口消息循环:员工查看公告板(消息队列)处理日常事务。
本章内容概览
- 6.8.0 LPC框架图:LPC机制完整架构;
- 6.8.1 LPC概述:定义、特点和应用场景;
- 6.8.2 LPC端口对象:端口类型和结构定义;
- 6.8.3 LPC通信流程:创建、连接、消息传递;
- 6.8.4 LPC安全机制:身份验证和模拟;
- 6.9.0 视窗报文框架图:消息系统架构;
- 6.9.1 消息机制概述:消息驱动架构;
- 6.9.2 消息发送方式:同步与异步;
- 6.9.3 消息队列与分发:队列结构和处理流程;
- 6.9.4 消息钩子与广播:监控和通知机制;
- 设计哲学问答:关键设计问题深入解答。
学习目标
读完本章后,读者应当能够:
- 理解LPC机制的内核实现原理;
- 掌握LPC端口类型和通信流程;
- 分析视窗报文系统的消息驱动模型;
- 理解SendMessage和PostMessage的区别;
- 掌握消息钩子和广播机制;
- 区分两种IPC机制的适用场景。
涉及的内核子系统
| 子系统 | 职责 |
|---|---|
| ntoskrnl/lpc | LPC核心实现(端口管理、消息传递) |
| win32ss/user/ntuser | 用户态消息处理(消息队列、钩子) |
| csrss | Win32子系统进程(LPC服务端) |
| ntdll | LPC用户态API(NtConnectPort等) |
6.8.0 LPC框架图
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ LPC 机制完整架构 │
├──────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 用户态 API 层 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ ntdll.dll │ │
│ │ ├─► NtCreatePort 创建连接端口 │ │
│ │ ├─► NtCreateWaitablePort 创建可等待端口 │ │
│ │ ├─► NtConnectPort 连接到端口 │ │
│ │ ├─► NtSecureConnectPort 安全连接(SID验证) │ │
│ │ ├─► NtRequestPort 发送数据报消息 │ │
│ │ ├─► NtRequestWaitReplyPort 发送请求并等待回复 │ │
│ │ ├─► NtListenPort 监听连接请求 │ │
│ │ ├─► NtAcceptConnectPort 接受连接 │ │
│ │ ├─► NtReplyPort 发送回复消息 │ │
│ │ └─► NtReplyWaitReceivePort 回复并等待下一条消息 │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 内核态实现层 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ ntoskrnl/lpc/ │ │
│ │ ├─► create.c: NtCreatePort, NtCreateWaitablePort │ │
│ │ ├─► connect.c: NtConnectPort, NtSecureConnectPort │ │
│ │ ├─► send.c: NtRequestPort, NtRequestWaitReplyPort │ │
│ │ ├─► receive.c: NtListenPort, NtAcceptConnectPort │ │
│ │ ├─► reply.c: NtReplyPort, NtReplyWaitReceivePort │ │
│ │ └─► close.c: LpcExitThread, LpcpDeletePort │ │
│ │ │ │
│ │ 核心数据结构 │ │
│ │ ├─► LPCP_PORT_OBJECT: 端口对象 │ │
│ │ ├─► LPCP_MESSAGE: 消息结构 │ │
│ │ ├─► PORT_MESSAGE: 消息头部 │ │
│ │ └─► PORT_VIEW: Section视图信息 │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ CSRSS 端口服务层 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ csrss.exe │ │
│ │ ├─► \Windows\ApiPort Win32 API请求处理 │ │
│ │ ├─► \Windows\SbApiPort 会话管理器接口 │ │
│ │ ├─► \Windows\SmApiPort 子系统管理接口 │ │
│ │ └─► \Console\LpcPort 控制台I/O接口 │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ LPC 通信模型 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 客户端进程 内核层 服务端进程 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ClientPort │─────────────►│ │◄─────────────│ConnPort │ │ │
│ │ │(客户端端口)│ NtConnectPort│ │NtListenPort │(连接端口)│ │ │
│ │ └────┬─────┘ │ │ └────┬─────┘ │ │
│ │ │ │ LPC子系统│ │ │ │
│ │ │ NtRequestWaitReplyPort │ NtAcceptConnectPort │ │
│ │ │ │ │ │ │ │
│ │ ▼ │ │ ▼ │ │
│ │ ┌──────────┐ │ │ ┌──────────┐ │ │
│ │ │CommPort │◄─────────────│ │─────────────►│CommPort │ │ │
│ │ │(通信端口)│ NtReplyPort │ │NtRequestPort │(通信端口)│ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────┘
6.8.1 LPC概述
6.8.1.1 LPC定义与核心特点
LPC(Local Procedure Call,本地过程调用)是Windows内核提供的高性能进程间通信机制:
核心特点:
| 特点 | 说明 |
|---|---|
| 内核级实现 | 直接在内核中传递消息,无需文件系统介入 |
| 请求-响应模型 | 同步通信,客户端阻塞等待服务器响应 |
| 消息大小限制 | 256字节(32位)/ 512字节(64位) |
| Section共享 | 支持大数据传输的内存映射机制 |
| 安全机制完善 | 支持SID验证和客户端身份模拟 |
| 仅限本地 | 不支持跨机器通信 |
6.8.1.2 LPC与其他IPC机制对比
| 特性 | LPC | 命名管道 | 共享内存 |
|---|---|---|---|
| 性能 | 最高 | 中等 | 最高 |
| 消息大小 | 有限 | 无限制 | 无限制 |
| 同步性 | 同步请求-响应 | 流模式 | 需额外同步 |
| 安全支持 | 完整 | 部分 | 需额外处理 |
| 通信范围 | 本地 | 本地/远程 | 本地 |
| 典型应用 | CSRSS通信 | 服务通信 | 大数据共享 |
6.8.1.3 LPC在Windows子系统中的应用
LPC是Win32子系统通信的核心:
CSRSS LPC端口架构
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ 应用程序 ──► NtConnectPort ──► \Windows\ApiPort ──► CSRSS │
│ │ │ │
│ │ CreateWindow请求 │ 创建窗口 │
│ │◄───────────── 窗口句柄 ────────────│ │
│ │
│ 应用程序 ──► NtConnectPort ──► \Console\LpcPort ──► CSRSS │
│ │ │ │
│ │ 控制台输入输出请求 │ 处理I/O │
│ │◄───────────── 结果 ──────────────│ │
│ │
└─────────────────────────────────────────────────────────────────────┘
6.8.2 LPC端口对象
6.8.2.1 端口类型
LPC支持四种端口类型:
| 端口类型 | 创建方式 | 用途 |
|---|---|---|
| 连接端口 | NtCreatePort |
服务端监听端口,接受连接请求 |
| 客户端端口 | NtConnectPort |
客户端连接端口,发起连接 |
| 通信端口 | 自动创建 | 连接建立后用于实际通信 |
| 可等待端口 | NtCreateWaitablePort |
可作为同步事件使用 |
6.8.2.2 LPCP_PORT_OBJECT结构
c
typedef struct _LPCP_PORT_OBJECT
{
struct _LPCP_PORT_OBJECT *ConnectionPort; // 连接端口引用
struct _LPCP_PORT_OBJECT *ConnectedPort; // 已连接端口
LPCP_PORT_QUEUE MsgQueue; // 消息队列
CLIENT_ID Creator; // 创建者标识
PVOID ClientSectionBase; // 客户端Section基址
PVOID ServerSectionBase; // 服务器Section基址
PVOID PortContext; // 端口上下文
SECURITY_QUALITY_OF_SERVICE SecurityQos; // 安全服务质量
ULONG MaxMessageLength; // 最大消息长度
ULONG Flags; // 端口标志
KEVENT WaitEvent; // 等待事件
} LPCP_PORT_OBJECT, *PLPCP_PORT_OBJECT;
源码位置:sdk/include/ndk/lpctypes.h#L209(file:///d:/reactos/sdk/include/ndk/lpctypes.h#L209)
6.8.2.3 PORT_MESSAGE消息头部
c
typedef struct _PORT_MESSAGE
{
USHORT DataLength; // 消息数据长度
USHORT TotalLength; // 总长度(含头部)
union
{
CLIENT_ID ClientId; // 客户端标识
ULONG_PTR ClientUniqueId; // 客户端唯一标识
};
ULONG MessageId; // 消息ID
ULONG MessageType; // 消息类型
} PORT_MESSAGE, *PPORT_MESSAGE;
消息类型枚举:
LPC_REQUEST:客户端请求LPC_REPLY:服务器回复LPC_DATAGRAM:数据报LPC_CONNECTION_REQUEST:连接请求
6.8.3 LPC通信流程
6.8.3.1 端口创建与连接
服务端创建连接端口:
c
NTSTATUS
NTAPI
NtCreatePort(OUT PHANDLE PortHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN ULONG MaxMessageLength,
IN ULONG MaxConnectionInfoLength)
{
// 验证参数
if (MaxMessageLength > LPC_MAX_MESSAGE_LENGTH)
return STATUS_INVALID_PARAMETER;
// 创建端口对象
Status = ObCreateObject(ExGetPreviousMode(),
LpcPortObjectType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(LPCP_PORT_OBJECT),
0,
0,
(PVOID*)&Port);
// 初始化端口队列
InitializeListHead(&Port->MsgQueue.ListHead);
// 设置端口标志为连接端口
Port->Flags = LPCP_CONNECTION_PORT;
return STATUS_SUCCESS;
}
源码位置:ntoskrnl/lpc/create.c#L222(file:///d:/reactos/ntoskrnl/lpc/create.c#L222)
客户端连接到端口:
c
NTSTATUS
NTAPI
NtConnectPort(OUT PHANDLE PortHandle,
IN PUNICODE_STRING PortName,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
IN OUT PLPC_SECTION_WRITE_DATA SectionData,
OUT PLPC_SECTION_READ_DATA *ReadData,
OUT PULONG ConnectionInfoLength,
IN PVOID ConnectionInfo,
IN ULONG ConnectionInfoLength)
{
// 解析端口名称
// 查找连接端口对象
// 创建客户端端口
// 发送连接请求
// 等待服务器接受
// 返回Section信息(如果有)
}
源码位置:ntoskrnl/lpc/connect.c#L777(file:///d:/reactos/ntoskrnl/lpc/connect.c#L777)
6.8.3.2 消息发送与接收
客户端发送请求(请求-响应模式):
c
NTSTATUS
NTAPI
NtRequestWaitReplyPort(IN HANDLE PortHandle,
IN PPORT_MESSAGE RequestMessage,
OUT PPORT_MESSAGE ReplyMessage)
{
// 验证消息长度
// 将消息放入目标端口队列
// 阻塞等待回复
// 返回回复消息
}
源码位置:ntoskrnl/lpc/send.c#L470(file:///d:/reactos/ntoskrnl/lpc/send.c#L470)
服务端接收并回复:
c
NTSTATUS
NTAPI
NtReplyWaitReceivePort(IN HANDLE PortHandle,
OUT PULONG MessageType,
OUT PPORT_MESSAGE ReplyMessage,
OUT PPORT_MESSAGE RequestMessage)
{
// 发送回复消息
// 等待下一条请求
// 返回请求消息
}
源码位置:ntoskrnl/lpc/reply.c#L743(file:///d:/reactos/ntoskrnl/lpc/reply.c#L743)
6.8.3.3 Section共享机制
PORT_VIEW结构:
c
typedef struct _PORT_VIEW
{
PVOID SectionBase; // Section基址
ULONG SectionSize; // Section大小
ULONG ViewSize; // 视图大小
ULONG ViewOffset; // 视图偏移
} PORT_VIEW, *PPORT_VIEW;
Section共享流程:
- 服务端创建Section对象;
- 连接时传递PORT_VIEW信息;
- 客户端映射Section到自己的地址空间;
- 双方通过共享内存传输大数据。
6.8.4 LPC安全机制
6.8.4.1 安全上下文传递
LPC支持两种安全跟踪模式:
| 模式 | 说明 |
|---|---|
| 静态安全跟踪 | 连接时建立安全上下文,后续通信复用 |
| 动态安全跟踪 | 每次消息发送时重新验证 |
6.8.4.2 客户端身份模拟
c
NTSTATUS
NTAPI
NtImpersonateClientOfPort(IN HANDLE PortHandle)
{
// 获取端口的安全上下文
// 将当前线程的令牌替换为客户端令牌
// 后续操作以客户端身份执行
}
应用场景:服务器需要以客户端身份访问资源时使用。
6.9.0 视窗报文框架图
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ 视窗报文系统完整架构 │
├──────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 用户态 API 层 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ user32.dll │ │
│ │ ├─► SendMessage 同步发送消息 │ │
│ │ ├─► PostMessage 异步投递消息 │ │
│ │ ├─► SendNotifyMessage 同步发送不等待回复 │ │
│ │ ├─► SendMessageTimeout 同步发送带超时 │ │
│ │ ├─► GetMessage 获取消息(阻塞) │ │
│ │ ├─► PeekMessage 查看消息(非阻塞) │ │
│ │ ├─► DispatchMessage 分发消息到窗口过程 │ │
│ │ ├─► SetWindowsHookEx 设置消息钩子 │ │
│ │ └─► BroadcastSystemMessage 广播消息 │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 内核态实现层 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ win32ss/user/ntuser/ │ │
│ │ ├─► message.c: NtUserSendMessage, NtUserPostMessage │ │
│ │ ├─► msgqueue.c: 消息队列管理 │ │
│ │ ├─► hook.c: 消息钩子实现 │ │
│ │ └─► winproc.c: 窗口过程调用 │ │
│ │ │ │
│ │ 核心数据结构 │ │
│ │ ├─► THREADINFO: 线程信息(含消息队列) │ │
│ │ ├─► MSG: 消息结构 │ │
│ │ └─► HOOK: 钩子结构 │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 消息队列层 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ SentMessagesListHead 发送消息队列(同步) │ │
│ │ PostedMessagesListHead 投递消息队列(异步) │ │
│ │ HardwareMessagesListHead 硬件输入队列 │ │
│ │ NotifyMessagesListHead 通知消息队列 │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │
│ 消息处理流程 │
│ ┌────────────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 发送方线程 内核层 接收方线程 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │SendMessage│─────────────►│ │─────────────►│窗口过程 │ │ │
│ │ │(同步阻塞) │ │ 消息子系统│ │(直接调用) │ │ │
│ │ │◄─────────│ │ │ │ │ │ │
│ │ │ 等待回复 │ │ │ │◄─────────│ │ │
│ │ └──────────┘ └──────────┘ │ 返回结果 │ │ │
│ │ └──────────┘ │ │
│ │ │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │PostMessage│─────────────►│ 消息队列 │◄─────────────│GetMessage│ │ │
│ │ │(异步返回) │ │ │ │(阻塞等待) │ │ │
│ │ └──────────┘ │ │ └────┬─────┘ │ │
│ │ │ │ │ │ │
│ │ └──────────┘ ▼ │ │
│ │ ┌──────────┐ │ │
│ │ │DispatchMsg│ │ │
│ │ │(分发消息) │ │ │
│ │ └──────────┘ │ │
│ └────────────────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────────────┘
6.9.1 消息机制概述
6.9.1.1 消息驱动架构
Windows采用事件驱动模型,所有用户交互通过消息传递:
消息驱动架构
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ 用户操作 ──► 系统生成消息 ──► 消息队列 ──► 消息循环 ──► 窗口过程 │
│ │ │ │
│ │ ▼ │
│ │ 处理消息并响应 │
│ │◄───────────────────────────────────│ │
│ │
└─────────────────────────────────────────────────────────────────────┘
6.9.1.2 消息类型分类
| 类型 | 示例 | 说明 |
|---|---|---|
| 窗口消息 | WM_CREATE, WM_DESTROY, WM_PAINT | 窗口生命周期和绘制 |
| 输入消息 | WM_KEYDOWN, WM_MOUSEMOVE | 用户输入 |
| 系统消息 | WM_TIMER, WM_QUIT | 系统通知 |
| 用户消息 | WM_USER+1, WM_APP+100 | 应用自定义消息 |
6.9.1.3 MSG结构
c
typedef struct tagMSG {
HWND hwnd; // 消息目标窗口
UINT message; // 消息标识符
WPARAM wParam; // 消息参数1
LPARAM lParam; // 消息参数2
DWORD time; // 消息时间戳
POINT pt; // 消息发生时的鼠标位置
} MSG, *PMSG;
6.9.2 消息发送方式
6.9.2.1 SendMessage(同步发送)
c
LRESULT
WINAPI
SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// 验证参数
// 检查是否跨线程/进程
// 直接调用目标窗口过程或排队等待
// 返回处理结果
}
源码位置:win32ss/user/ntuser/message.c#L1707(file:///d:/reactos/win32ss/user/ntuser/message.c#L1707)(co_IntSendMessageTimeout)
特点:同步阻塞,等待目标窗口过程返回。
6.9.2.2 PostMessage(异步投递)
c
BOOL
WINAPI
PostMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// 验证参数
// 将消息放入目标线程队列
// 立即返回
}
源码位置:win32ss/user/ntuser/message.c#L2275(file:///d:/reactos/win32ss/user/ntuser/message.c#L2275)(NtUserPostMessage)
特点:异步非阻塞,消息放入队列后立即返回。
6.9.2.3 发送方式对比
| 特性 | SendMessage | PostMessage |
|---|---|---|
| 同步性 | 同步阻塞 | 异步非阻塞 |
| 返回值 | 窗口过程返回值 | 投递是否成功 |
| 消息队列 | 不使用队列 | 使用投递队列 |
| 跨进程 | 支持(需特殊处理) | 支持(需特殊处理) |
| 优先级 | 高(立即处理) | 低(排队处理) |
6.9.3 消息队列与分发
6.9.3.1 线程消息队列结构
c
typedef struct _THREADINFO {
// 消息队列
LIST_ENTRY SentMessagesListHead; // 发送消息队列
LIST_ENTRY PostedMessagesListHead; // 投递消息队列
LIST_ENTRY HardwareMessagesListHead; // 硬件输入队列
// 等待标志
ULONG fsWakeBits; // 当前等待标志
ULONG fsWakeBitsMask; // 等待掩码
// 消息事件
KEVENT MessageEvent; // 消息到达事件
// 消息钩子
PHOOK aphkStart[WH_MAXHOOK]; // 钩子数组
} THREADINFO, *PTHREADINFO;
6.9.3.2 GetMessage处理流程
源码位置:win32ss/user/ntuser/message.c#L2343(file:///d:/reactos/win32ss/user/ntuser/message.c#L2343)(NtUserGetMessage)
GetMessage处理顺序
1. 检查QS_SENDMESSAGE → 处理发送消息队列
2. 检查QS_POSTMESSAGE → 处理投递消息队列
3. 检查QS_INPUT → 处理硬件输入队列
4. 检查QS_PAINT → 生成WM_PAINT消息
5. 检查QS_TIMER → 生成WM_TIMER消息
6. 无消息 → 等待MessageEvent
6.9.3.3 标准消息循环
c
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg); // 转换键盘消息
DispatchMessage(&msg); // 分发到窗口过程
}
源码位置:win32ss/user/ntuser/message.c#L890(file:///d:/reactos/win32ss/user/ntuser/message.c#L890)(IntDispatchMessage)
6.9.4 消息钩子与广播
6.9.4.1 消息钩子类型
| 钩子类型 | 触发时机 | 用途 |
|---|---|---|
| WH_CALLWNDPROC | 窗口过程调用前 | 监控SendMessage |
| WH_CALLWNDPROCRET | 窗口过程返回后 | 监控消息返回值 |
| WH_GETMESSAGE | GetMessage返回后 | 监控投递消息 |
| WH_KEYBOARD | 键盘消息到达时 | 键盘钩子 |
| WH_MOUSE | 鼠标消息到达时 | 鼠标钩子 |
6.9.4.2 钩子处理流程
源码位置:win32ss/user/ntuser/hook.c#L1102(file:///d:/reactos/win32ss/user/ntuser/hook.c#L1102)(co_HOOK_CallHooks)
消息钩子链
消息产生 ──► Hook1 ──► Hook2 ──► ... ──► 窗口过程
│ │
CallNextHookEx CallNextHookEx
6.9.4.3 广播消息
BroadcastSystemMessage:向指定类型接收者发送消息;
HWND_BROADCAST:向所有顶层窗口发送消息(内核实现:win32ss/user/ntuser/message.c#L2654(file:///d:/reactos/win32ss/user/ntuser/message.c#L2654));
c
// 发送系统设置变更通知
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)L"Environment");
设计哲学问答
Q1:LPC为什么限制消息大小为256/512字节?
A:LPC设计目标是高性能的请求-响应通信,小消息可以:
- 使用Lookaside列表快速分配;
- 避免复杂的内存管理;
- 保证快速的消息传递。
大数据传输通过Section共享机制实现。
Q2:为什么SendMessage需要同步阻塞?
A:SendMessage用于需要立即获取结果的场景,如获取窗口文本、查询状态等。同步阻塞保证调用者能立即获得返回值。
Q3:LPC如何保证安全性?
A:LPC通过以下机制保证安全:
- SID验证(NtSecureConnectPort);
- 安全上下文传递;
- 客户端身份模拟;
- 静态/动态安全跟踪。
Q4:消息队列为什么分为发送队列和投递队列?
A:发送队列用于同步消息(SendMessage),需要立即处理;投递队列用于异步消息(PostMessage),按顺序处理。分离设计提高了消息处理效率。
Q5:LPC和视窗报文的适用场景有何不同?
A:LPC适用于系统级组件间的高性能请求-响应通信;视窗报文适用于GUI应用的事件驱动交互。LPC是内核级机制,视窗报文是用户态机制。
源码索引
LPC核心源码
| 文件路径 | 行号 | 说明 |
|---|---|---|
sdk/include/ndk/lpctypes.h |
121 | PORT_MESSAGE结构定义 |
sdk/include/ndk/lpctypes.h |
209 | LPCP_PORT_OBJECT结构定义 |
sdk/include/ndk/lpctypes.h |
281 | PORT_VIEW结构定义 |
ntoskrnl/include/internal/lpc.h |
100 | LPC内部函数声明 |
ntoskrnl/include/internal/lpc_x.h |
99 | LpcpAllocateFromPortZone等内联函数 |
ntoskrnl/lpc/create.c |
222 | NtCreatePort实现 |
ntoskrnl/lpc/connect.c |
80 | NtSecureConnectPort实现 |
ntoskrnl/lpc/connect.c |
777 | NtConnectPort实现 |
ntoskrnl/lpc/send.c |
440 | NtRequestPort实现 |
ntoskrnl/lpc/send.c |
470 | NtRequestWaitReplyPort实现 |
ntoskrnl/lpc/reply.c |
190 | NtReplyPort实现 |
ntoskrnl/lpc/reply.c |
360 | NtReplyWaitReceivePortEx实现 |
ntoskrnl/lpc/reply.c |
743 | NtReplyWaitReceivePort实现 |
ntoskrnl/lpc/listen.c |
22 | NtListenPort实现 |
ntoskrnl/lpc/complete.c |
40 | NtAcceptConnectPort实现 |
ntoskrnl/lpc/close.c |
25 | LpcExitThread、LpcpDeletePort |
视窗报文核心源码
| 文件路径 | 行号 | 说明 |
|---|---|---|
win32ss/user/ntuser/message.c |
890 | IntDispatchMessage分发消息 |
win32ss/user/ntuser/message.c |
1285 | 消息指针处理逻辑 |
win32ss/user/ntuser/message.c |
1376 | UserPostMessage投递消息 |
win32ss/user/ntuser/message.c |
1510 | SendMessageTimeoutSingle |
win32ss/user/ntuser/message.c |
1707 | co_IntSendMessageTimeout |
win32ss/user/ntuser/message.c |
2275 | NtUserPostMessage内核调用 |
win32ss/user/ntuser/message.c |
2343 | NtUserGetMessage获取消息 |
win32ss/user/ntuser/message.c |
2464 | NtUserDispatchMessage |
win32ss/user/ntuser/msgqueue.c |
731 | MsqCreateMessage创建消息 |
win32ss/user/ntuser/msgqueue.c |
1355 | 消息入队处理 |
win32ss/user/ntuser/msgqueue.c |
2396 | MsqCreateMessageQueue |
win32ss/user/ntuser/hook.c |
1102 | co_HOOK_CallHooks调用钩子 |
win32ss/user/ntuser/hook.c |
1429 | NtUserSetWindowsHookEx设置钩子 |
总结
LPC核心要点
- 内核级IPC:高性能本地通信,直接在内核中传递消息;
- 请求-响应模型:同步通信,客户端阻塞等待服务器响应;
- 端口对象:四种端口类型,支持连接、通信和同步;
- Section共享:支持大数据传输,避免消息复制开销;
- 安全机制:支持SID验证和客户端身份模拟;
- 典型应用:CSRSS与应用程序通信。
视窗报文核心要点
- 消息驱动:Windows GUI的核心事件处理机制;
- 同步与异步:SendMessage同步,PostMessage异步;
- 消息队列:发送队列、投递队列、输入队列分离;
- 钩子机制:允许监控和拦截消息;
- 广播消息:支持系统级通知。
两种IPC机制对比
| 特性 | LPC | 视窗报文 |
|---|---|---|
| 层次 | 内核态 | 用户态/内核态 |
| 通信模式 | 请求-响应 | 同步/异步消息传递 |
| 数据大小 | 有限(256/512字节) | 消息参数限制 |
| 大数据支持 | Section共享 | WM_COPYDATA |
| 典型应用 | CSRSS通信 | GUI消息循环 |
| 性能 | 极高 | 中高 |
文档完成
本章详细介绍了Windows/ReactOS中的两种核心IPC机制:LPC和视窗报文系统。LPC作为内核级IPC机制,为系统组件提供高性能通信;视窗报文系统则是GUI应用的核心,实现了窗口间的消息传递。理解这两种机制对于深入理解Windows操作系统的工作原理至关重要。