rk3588/kernel-6.1 IPC 架构与实现原理分析

rk3588/kernel-6.1 IPC 架构与实现原理分析

1. IPC 子系统用途概览

ipc/ 目录实现 Linux 内核中的进程间通信核心能力,主要包括:

  • System V IPC
    • 消息队列(msg.c
    • 信号量(sem.c
    • 共享内存(shm.c
  • POSIX Message Queue
    • 消息队列文件系统与系统调用(mqueue.c
  • IPC 命名空间
    • 隔离不同容器/命名空间的 IPC 对象(namespace.c
  • 通用框架
    • IPC ID 分配、权限、生命周期与并发模型(util.c/.h

简化理解:
ipc/ 是“对象管理层 + 同步/消息语义层 + namespace 隔离层”的组合。


2. 编译与配置入口

2.1 Kconfig

位于 init/Kconfig 的关键项:

  • SYSVIPC:启用 SysV IPC
  • POSIX_MQUEUE:启用 POSIX 消息队列(依赖 NET
  • IPC_NS:启用 IPC namespace(依赖 SYSVIPC || POSIX_MQUEUE
  • SYSVIPC_SYSCTLPOSIX_MQUEUE_SYSCTL:对应 sysctl 配置接口

2.2 Makefile

ipc/Makefile 体现模块分层:

  • obj-$(CONFIG_SYSVIPC)util.o msgutil.o msg.o sem.o shm.o syscall.o
  • obj-$(CONFIG_POSIX_MQUEUE)mqueue.o msgutil.o
  • obj-$(CONFIG_IPC_NS)namespace.o
  • obj-$(CONFIG_*_SYSCTL):sysctl 参数支持

3. 总体架构分层

可分为四层:

  1. 系统调用入口层

    • 现代路径:msgget/msgsnd/msgrcvsemget/semtimedop/semctlshmget/shmat/shmdt/shmctlmq_*
    • 兼容路径:ipc/syscall.csys_ipc 复用旧多路复用接口
  2. 通用对象管理层(SysV 共用)

    • ipc_ids + idr + rhashtable 管理对象 ID 与 key 查找
    • ipc_addid/ipc_rmid/ipcget/ipcperms 提供统一创建/查找/鉴权逻辑
    • ipc_ops{getnew, associate, more_checks} 抽象 msg/sem/shm 的差异
  3. 机制实现层

    • msg.c:消息队列收发/阻塞唤醒
    • sem.c:信号量集合、原子 semop、undo 机制
    • shm.c:共享内存段创建、映射、拆映射
    • mqueue.c:POSIX mqueue 的 VFS 化实现
  4. 隔离与可观测层

    • namespace.c:IPC namespace 创建、切换、销毁
    • ipc_sysctl.c/mq_sysctl.c:运行时参数调优
    • /proc/sysvipc/*:对象状态观测

4. 通用实现原理(SysV IPC 核心骨架)

4.1 对象标识设计

util.h 中 ID 由 index + sequence 组成:

  • ipcid_to_idx() 取索引
  • ipcid_to_seqx() 校验序号
  • 防止“ID 被回收后复用”导致陈旧句柄误命中

4.2 ipcget() 统一建/取流程

msgget/semget/shmget 都走类似流程:

  1. 构造 ipc_opsgetnew/associate/more_checks
  2. 通过 key 在 ipc_ids 查找对象
  3. 找不到且允许创建时,调用 getnew() 分配对象
  4. 执行 LSM 安全检查与权限校验

这让三类 SysV IPC 在入口逻辑一致,语义差异下沉到各自文件。

4.3 并发与锁模型

util.c 顶部注释给出关键模型:

  • ids->rwsem:保护 IPC 集合(创建/删除/遍历)
  • kern_ipc_perm.lock:保护单个 IPC 对象状态
  • RCU:支持 lockless 查找和并发删除期间安全访问

总体思想:集合级 rwsem + 对象级 spinlock + RCU 生命周期


5. 三大 SysV IPC 机制

5.1 消息队列(msg.c

用途

  • 进程间按消息粒度交换数据,支持类型匹配(msgtyp)。

核心调用链

  • 创建:msgget -> ksys_msgget -> ipcget(..., newque, ...)
  • 发送:msgsnd -> ksys_msgsnd -> do_msgsnd
  • 接收:msgrcv -> ksys_msgrcv -> do_msgrcv
  • 控制:msgctlIPC_SET/IPC_RMID/IPC_STAT 等)

实现要点

  • 队列满时,发送方进入等待队列;IPC_NOWAIT 下直接 -EAGAIN
  • 接收方按 msgtyp 策略筛选(SEARCH_ANY/EQUAL/LESSEQUAL/...
  • 支持“管线化发送/接收”(pipelined_send),减少中间排队开销
  • 删除队列时 freeque() 负责唤醒阻塞 sender/receiver 并回收消息

5.2 信号量(sem.c

用途

  • 对共享资源做计数同步与互斥控制。

核心调用链

  • 创建:semget -> ksys_semget -> ipcget(..., newary, ...)
  • 操作:semop/semtimedop -> do_semtimedop -> __do_semtimedop
  • 控制:semctl -> semctl_main

实现要点

  • newary() 创建的是 信号量集合nsems 个)
  • perform_atomic_semop() 保证一个 sembuf[] 批操作的原子语义
  • SEM_UNDO 记录进程级 undo,进程异常退出可回滚影响
  • 不可满足操作条件时可阻塞等待,超时/信号打断返回对应错误

5.3 共享内存(shm.c

用途

  • 多进程共享一段虚拟内存,适合大数据低拷贝通信。

核心调用链

  • 创建:shmget -> ksys_shmget -> ipcget(..., newseg, ...)
  • 挂接:shmat -> do_shmat
  • 脱离:shmdt -> ksys_shmdt
  • 控制:shmctl -> shmctl_down

实现要点

  • newseg() 基于 shmemhugetlb 创建后端文件对象
  • do_shmat() 完成权限检查、地址对齐策略、do_mmap 映射
  • shmdt 会处理被 mremap/munmap 改写后的复杂 VMA 拆卸场景
  • 通过 shm_nattchshm_may_destroy 管理段生命周期

6. POSIX 消息队列(mqueue.c

6.1 用途与模型

  • 提供 mq_open/mq_timedsend/mq_timedreceive/mq_notify 等 POSIX API。
  • 与 SysV msg 的差异:VFS 对象化 + 优先级消息 + 命名队列路径语义

6.2 核心调用链

  • mq_open -> do_mq_open(在当前 IPC namespace 的 mq_mnt 下查找/创建)
  • mq_timedsend -> do_mq_timedsend
  • mq_timedreceive -> do_mq_timedreceive

6.3 实现要点

  • 队列底层是 mqueue 文件系统 inode(mqueue_get_inode
  • 发送/接收使用自旋锁 + 等待队列管理并发
  • 支持 sender/receiver“直接管线化交付”,避免总是入队再出队
  • 定时版本通过绝对超时参数实现可中断等待

7. IPC Namespace 实现原理(namespace.c

7.1 创建

  • copy_ipcs(CLONE_NEWIPC) -> create_ipc_ns()
  • 初始化 mq/msg/sem/shm 各子系统与 sysctl
  • 将对象隔离到新的 ipc_namespace

7.2 销毁

  • put_ipc_ns() 引用计数归零后异步释放
  • free_ipc_ns() 顺序清理 sem/msg/shm/mqueue 对象与 sysctl

7.3 意义

  • 不同容器拥有独立 IPC 视图(ID 空间、对象集合、限制参数互不干扰)。

8. 安全与权限控制

IPC 路径中有三层权限约束:

  • 经典权限位检查ipcperms()
  • 能力检查:如 CAP_SYS_RESOURCECAP_SYS_ADMIN
  • LSM Hooksecurity_msg_* / security_sem_* / security_shm_*

因此 IPC 访问不仅受 uid/gid 控制,也受安全模块策略控制。


9. 调优与排障建议

  1. 对象创建失败(ENOSPC/ENOMEM)

    • 检查 msgmni/msgmnb/msgmaxsemmni/semmnsshm_ctl* 限制
    • 检查 namespace 下是否资源已耗尽
  2. 阻塞超时或吞吐低

    • 消息队列是否频繁满队列(sender 阻塞)
    • semop 是否存在热点 semaphore 争用
    • shm 方案是否更适合高吞吐场景
  3. 容器中 IPC 行为异常

    • 确认是否在预期的 IPC namespace
    • 检查容器 runtime 的 --ipc 模式与挂载的 mqueuefs
  4. 兼容接口问题

    • 关注 sys_ipc 老接口与 compat 路径参数差异
    • 注意 IPC_OLD/IPC_64 结构体转换逻辑

10. 一句话总结

ipc/ 的本质是:
util.c 提供统一对象管理与并发骨架,分别实现 msg/sem/shm 三类 SysV IPC 与 mqueue POSIX IPC,并通过 IPC namespace 提供容器级隔离。

文章互动

阅读 --

留言

0 条留言

正在加载留言…