XNU IPC

XNU 是所有 Apple 操作系统的核心,它是基于 Mach kernel 和 FreeBSD 组件。

微内核的设计 只提供内核空间需要的功能的最低限度,例如:线程、内存管理和IPC。

附加功能放置在单独的模块中,模块间可以利用 IPC 进行通信

Mach Message

这是 Mach kernel 中唯一使用的 IPC 机制。

这里就需要用到 对应的 数据结构来编写我们的 Mach Message

mach_msg_headre_t

typedef   struct 
{
  mach_msg_bits_t     msgh_bits;           // 一些消息标志位
  mach_msg_size_t     msgh_size;           // 消息 header + body + data 的总大小
  mach_port_t         msgh_remote_port;    // 目标 port right
  mach_port_t         msgh_local_port;     // 辅助 port right
  mach_port_name_t    msgh_voucher_port;
  mach_msg_id_t       msgh_id;            // 传递 mach msg 时不会使用该字段,用户可自行设置该字段
} mach_msg_header_t;

mach_msg_body_t

typedef struct
{
        mach_msg_size_t msgh_descriptor_count;
} mach_msg_body_t;

mach_msg_trailer_t

// mach/message.h

#define MACH_RCV_TRAILER_NULL   0

typedef struct {
  mach_msg_trailer_type_t       msgh_trailer_type;
  mach_msg_trailer_size_t       msgh_trailer_size;
} mach_msg_trailer_t;

其中结构 还包括 对应的我们要传入的数据,这里我们可以自己定义

交换信息 mach_msg 函数

mach_msg_return_t mach_msg(
  mach_msg_header_t *msg,         // 指向 massage 的结构体指针
  mach_msg_option_t option,       // 消息的选项 MACH_SEND_MSG 等
  mach_msg_size_t send_size,      // 我们发送的 massgae 的大小
  mach_msg_size_t rcv_size,       // 我们接收的 massgae 大小
  mach_port_name_t rcv_name,      // 接收的端口 
  mach_msg_timeout_t timeout,     // timeout 设置
  mach_port_name_t notify);       // 一个通知端口,类似于凭证,它是可选的

# 对应的函数
mach_msg_return_t
mach_msg_send(mach_msg_header_t *msg)
{
    return mach_msg(msg, MACH_SEND_MSG,
            msg->msgh_size, 0, MACH_PORT_NULL,
            MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
}

mach_msg_return_t
mach_msg_receive(mach_msg_header_t *msg)
{
    return mach_msg(msg, MACH_RCV_MSG,
            0, msg->msgh_size, msg->msgh_local_port,
            MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
}

对应的消息结构

// 第一种
typedef struct {
  mach_msg_header_t header;
  char bodyStr[32];
  int bodyInt;
} Message;

// 第二种 带 trailer 的
typedef struct {
  mach_msg_header_t header;
  char bodyStr[32];
  int bodyInt;

  mach_msg_trailer_t trailer;
} Message;

Mach API 使用

单向发送