mach_msg_header_t详解

13 阅读2分钟

借助AI能力分析。

mach_msg_header_t - Mach 消息头

作用

这是 Mach 消息的头部结构,用于在 macOS/iOS 的进程间(或线程间)传递消息。

6个字段详解

typedef struct {
    mach_msg_bits_t      msgh_bits;         // 消息标志位
    mach_msg_size_t      msgh_size;         // 消息总大小(字节)
    mach_port_t          msgh_remote_port;  // 目标端口(收信人)
    mach_port_t          msgh_local_port;   // 本地端口(回信地址)
    mach_port_name_t     msgh_voucher_port; // 追踪端口(调试用)
    mach_msg_id_t        msgh_id;           // 消息ID(自定义)
} mach_msg_header_t;

形象比喻(信封):

字段对应信封上的说明
msgh_remote_port收件人地址消息发往哪个端口
msgh_local_port回信地址如果需要回复,发到这里
msgh_size信件大小包括信封和内容
msgh_bits邮寄方式挂号信、平信等
msgh_id信件编号用于区分不同类型的信
msgh_voucher_port追踪单号用于追踪和调试

在 RunLoop 中的使用

1. 发送唤醒消息(CFRunLoopWakeUp)

// 构造消息头
mach_msg_header_t header;
header.msgh_remote_port = rl->_wakeUpPort;  // 发往唤醒端口
header.msgh_local_port = MACH_PORT_NULL;    // 不需要回复
header.msgh_size = sizeof(mach_msg_header_t); // 只有头,无内容
header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
header.msgh_id = 0;

// 发送(唤醒 RunLoop)
mach_msg(&header, MACH_SEND_MSG, ...);

2. 接收消息(RunLoop 休眠)

// 准备缓冲区
uint8_t buffer[3 * 1024];
mach_msg_header_t *msg = (mach_msg_header_t *)buffer;

msg->msgh_local_port = waitSet;  // 在哪个端口等待
msg->msgh_size = sizeof(buffer);  // 缓冲区大小

// 阻塞等待(线程休眠)
mach_msg(msg, MACH_RCV_MSG, ...);

// 被唤醒后,检查消息来源
if (msg->msgh_local_port == _wakeUpPort) {
    // 手动唤醒
} else if (msg->msgh_local_port == _timerPort) {
    // 定时器到期
}

关键理解

mach_msg_header_t 是 Mach IPC 的核心

  1. 通信基础:所有 Mach 消息都以这个头开始
  2. 路由信息:指明消息的来源和去向
  3. RunLoop 休眠/唤醒:通过接收/发送消息实现

完整消息结构

┌──────────────────────┐
│ mach_msg_header_t    │ ← 消息头(必需)
├──────────────────────┤
│ 消息体(可选)        │ ← 实际数据
├──────────────────────┤
│ trailer(可选)       │ ← 附加信息
└──────────────────────┘

RunLoop 的简化消息:只有头部,无消息体(称为 "trivial message"),足以唤醒线程。