Reactos 第 6 章 进程间通信 — 6.8 本地过程调用(LPC)与 6.9 视窗报文(Message)

第 6 章 进程间通信 --- 6.8 本地过程调用(LPC)与 6.9 视窗报文(Message)

本章深入剖析 Windows/ReactOS 中两种核心进程间通信机制:LPC(本地过程调用)和视窗报文系统。

概述

进程间通信(IPC)是现代操作系统的核心功能,Windows 提供了多种 IPC 机制来满足不同场景的需求。本章重点介绍两种特殊的IPC机制:

LPC 和视窗报文的本质区别是什么?

LPC 是内核级的高性能请求-响应机制,专为系统组件间的高效通信设计;视窗报文系统则是用户态GUI应用的事件驱动核心,实现窗口间的消息传递。两者服务于不同层次,但共同构成了Windows的通信基础设施。

想象一个企业办公场景:

  • LPC:部门之间的内部电话系统,快速、可靠的请求-响应交互;
  • 视窗报文:办公室的公告板和内部邮件系统,异步消息传递和事件通知;
  • CSRSS与应用程序通信:员工通过内部电话向IT部门(CSRSS)请求服务;
  • 窗口消息循环:员工查看公告板(消息队列)处理日常事务。

本章内容概览

  1. 6.8.0 LPC框架图:LPC机制完整架构;
  2. 6.8.1 LPC概述:定义、特点和应用场景;
  3. 6.8.2 LPC端口对象:端口类型和结构定义;
  4. 6.8.3 LPC通信流程:创建、连接、消息传递;
  5. 6.8.4 LPC安全机制:身份验证和模拟;
  6. 6.9.0 视窗报文框架图:消息系统架构;
  7. 6.9.1 消息机制概述:消息驱动架构;
  8. 6.9.2 消息发送方式:同步与异步;
  9. 6.9.3 消息队列与分发:队列结构和处理流程;
  10. 6.9.4 消息钩子与广播:监控和通知机制;
  11. 设计哲学问答:关键设计问题深入解答。

学习目标

读完本章后,读者应当能够:

  • 理解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共享流程:

  1. 服务端创建Section对象;
  2. 连接时传递PORT_VIEW信息;
  3. 客户端映射Section到自己的地址空间;
  4. 双方通过共享内存传输大数据。

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操作系统的工作原理至关重要。

相关推荐
caimouse2 小时前
Reactos 第 6 章 进程间通信
windows
私人珍藏库2 小时前
【PC】ActivePresenter(屏幕录制软件) Pro v10.5.1 多语便携版
windows·pc·工具·软件·多功能
你住过的屋檐2 小时前
【claude code】claude code在windows下安装使用教程,以及在idea中使用claude code自动AI写代码
人工智能·windows·intellij-idea
caimouse2 小时前
Reactos 第 5 章 进程与线程 — 5.13 Windows的跨进程操作
windows
shen121383 小时前
【cdp】windows持久化运行cdp浏览器
windows·agent·cdp
W优化大师3 小时前
Windows电脑频繁弹广告怎么彻底清除?从定位来源到卸载残留的完整方法
windows·电脑
拼搏的小浣熊3 小时前
【通用教程】Windows\+Linux\+银河麒麟系统 固定静态IP地址|解决打印机扫描IP变动、网络掉线问题
linux·网络·windows·麒麟·固定ip·麒麟系统·统信系统
w3296362713 小时前
使用 OpenCode 在 Windows 上加速安装 Playwright 的完整指南
windows·git
dabidai3 小时前
Docker PostgreSQL Windows 权限问题总结
windows·docker·postgresql