首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

io_uring/ 异步 I/O 机制与原理详解

io_uring/ 异步 I/O 机制与原理详解

源码路径rk3588/kernel-6.1/io_uring/
内核版本:Linux 6.1(RK3588 / ARM64)
文档目录linuxDoc/io_uring/

io_uring 是 Linux 的高性能异步 I/O 接口:用户态与内核 共享 SQ/CQ 环形队列,通过 io_uring_setup / io_uring_enter / io_uring_register 三个系统调用完成提交与收割,多数路径可避免传统 read/write + 线程池的 syscall 开销。


目录


一、子系统职责

职责 实现
环创建与 mmap io_uring.cio_uring_create、SQE 数组、CQ 环
批量提交 io_submit_sqesio_submit_sqeio_issue_sqe
完成上报 io_get_cqe__io_commit_cqring_flush、overflow 链表
操作分派 opdef.cio_op_defs[opcode]
同步路径放不下的 I/O io-wq.c:per-task worker 池
内核代提 SQ sqpoll.cIORING_SETUP_SQPOLL
预注册 fd/缓冲区 rsrc.cfiletable.c
块/NVMe 等驱动命令 uring_cmd.c + 驱动 io_uring_cmd
网络异步 net.c
poll/epoll/timeout poll.cepoll.ctimeout.c

二、架构分层

flowchart TB
    subgraph app [用户态]
        A1[liburing / 自研]
    end
    subgraph syscall [系统调用]
        S1[io_uring_setup]
        S2[io_uring_enter]
        S3[io_uring_register]
    end
    subgraph core [io_uring.c]
        C1[io_ring_ctx]
        C2[submit / complete]
    end
    subgraph dispatch [opdef + 模块]
        D1[rw.c fs.c net.c ...]
        D2[uring_cmd.c]
    end
    subgraph async [io-wq / sqpoll]
        W1[io-wq workers]
        W2[SQ poll thread]
    end
    subgraph kernel [内核子系统]
        K1[VFS block net]
    end
    app --> syscall --> core --> dispatch
    dispatch --> async
    dispatch --> kernel
    async --> kernel

三、数据流概览

  1. setup:分配 io_ring_ctx,mmap SQ ring、CQ ring、SQE 数组(offsets 由 io_uring_params 返回)
  2. submit:用户写 SQE、推进 sq.tailio_uring_enter(to_submit) 或 SQPOLL 线程调用 io_submit_sqes
  3. issue:每个 SQE 对应 io_kiocbio_issue_sqe 调用 prep(提交前)与 issue
  4. complete:结果写入 CQ,io_uring_enter(GETEVENTS) 或 eventfd 唤醒;支持 LINKmultishot pollCQE32

四、Kconfig 与模块划分

  • CONFIG_IO_URING:主开关,默认开启
  • CONFIG_IO_WQ:异步工作队列(被 io_uring 选中)
  • 各 opcode 在 opdef.c#if defined(CONFIG_NET) 等裁剪 prepio_eopnotsupp_prep

详见 源码目录与模块索引.md


五、RK3588 说明

  • 源码树中 无 Rockchip 补丁;行为由通用 6.1 io_uring 决定
  • RK3588(ARM64 + GIC + eMMC/NVMe + 千兆网)适用场景:高 QPS 存储、网络代理、用户态协议栈
  • 注意 memlock 限制(注册缓冲区)、big.LITTLE 上与 IORING_SETUP_SQ_AFF / IOWQ_AFF 绑核

详见 07


功能组专题

编号 文档
01 核心接口与环机制与实现详解.md
02 提交与完成路径机制与实现详解.md
03 操作码与opdef分派机制与实现详解.md
04 异步执行与SQPOLL机制与实现详解.md
05 轮询超时与取消机制与实现详解.md
06 资源注册与URING_CMD机制与实现详解.md
07 RK3588平台关联与使用场景详解.md

rk3588/kernel-6.1 io_uring 模块架构与实现原理

rk3588/kernel-6.1 io_uring 模块架构与实现原理

1. 模块定位与编译入口

io_uring 是 Linux 6.1 中高性能异步 I/O 框架,核心思想是:

  • 用户态与内核态共享 SQ/CQ Ring 内存,减少系统调用与拷贝成本;
  • 通过统一 SQE opcode 抽象,覆盖文件、网络、超时、poll、资源注册等多类异步操作;
  • task_workio-wqSQPOLLIOPOLL 等机制平衡时延与吞吐。

在本内核树中:

  • 配置入口:init/Kconfigconfig IO_URING(默认 y,并 select IO_WQ);
  • IO_WQ 定义位于 fs/Kconfig
  • 构建入口:io_uring/Makefile,由 io_uring.o + opdef.o + 各 opcode 子模块(rw.cnet.ctimeout.cpoll.c 等)组成。

2. 目录分层(按职责)

io_uring/ 目录可分为 5 层:

  1. 核心控制层

    • io_uring.c:syscall 入口、ring 创建/销毁、提交流程、完成队列提交、等待逻辑。
    • io_uring.h:核心内联与跨文件函数声明。
    • include/linux/io_uring_types.h:核心结构定义(io_ring_ctxio_kiocbio_rings)。
  2. opcode 分发表与调度层

    • opdef.c/.hio_op_defs[],定义每个 opcode 的 prep/issue/cleanup/fail 能力与约束。
  3. 执行后端层

    • io-wq.c/.h:内核 worker 池(阻塞/慢路径异步执行)。
    • sqpoll.c/.h:SQ 轮询线程(减少用户提交 syscall)。
    • poll.c:fast poll 与轮询唤醒链路。
  4. 功能子模块层(按 opcode 家族)

    • 文件/元数据:rw.cfs.copenclose.cstatx.cxattr.csync.csplice.cadvise.c
    • 网络:net.cmsg_ring.curing_cmd.c
    • 时间与取消:timeout.ccancel.c
    • 资源管理:rsrc.ckbuf.cfiletable.ctctx.c
    • 观测支持:fdinfo.cnotif.c
  5. 共享工具层

    • alloc_cache.hrefs.hslist.h 等通用基础设施。

3. 核心数据结构

3.1 struct io_rings(用户态共享 ring 元数据)

  • 包含 sq.head/tailcq.head/tail、mask、entries、sq_droppedcq_overflowcqes[]
  • 职责边界清晰:用户写 SQ tail / 读 CQ tail内核写 SQ head / CQ tail

3.2 struct io_ring_ctx(每个 ring fd 一个上下文)

  • 提交面:uring_locksq_arraysq_sqessubmit_state、固定文件/缓冲资源。
  • 完成面:completion_lock、CQ 缓存指针、cq_wait、overflow list。
  • 异步面:iopoll_listwork_llistsq_data(SQPOLL)、io_wq 关联。
  • 资源面:file_tableuser_bufsrsrc_nodepersonalityrestrictions

3.3 struct io_kiocb(单请求对象)

  • 绑定 opcode 与请求态:opcodeflagscqefiletasklink
  • 支持多态命令区:cmd.data[56] 供各子模块覆盖使用。
  • 维护生命周期与异步状态:refspoll_refsasync_dataio_task_workwork

3.4 io_op_defs[](操作语义表)

  • 每个 opcode 定义:
    • 是否需要文件、是否支持 iopoll、是否支持 buffer select;
    • prep() 参数解析;
    • issue() 执行;
    • cleanup()/fail() 兜底路径。
  • 使 opcode 扩展呈“声明式分发表 + 独立模块实现”结构。

4. 三条主调用链

4.1 创建链:io_uring_setup -> io_uring_create

  1. SYSCALL_DEFINE2(io_uring_setup) 进入;
  2. 校验 io_uring_params.flags
  3. io_uring_create()
    • 计算并规范化 sq_entries/cq_entries(默认 cq=2*sq);
    • io_ring_ctx_alloc() 创建上下文;
    • io_allocate_scq_urings() 分配共享 ring 与 SQE 区;
    • io_sq_offload_create() 建立 SQPOLL/附加 WQ;
    • 初始化 sq_off/cq_off/features 返回给用户态;
    • anon_inode_getfile_secure() 创建 ring file;
    • io_uring_install_fd() 安装 fd。

实现要点:通过一个匿名 fd 对外暴露 ring,用户再通过 mmap 映射 SQ/CQ 与 SQE 区。

4.2 提交链:io_uring_enter -> io_submit_sqes

  1. SYSCALL_DEFINE6(io_uring_enter) 获取 ctx;
  2. 非 SQPOLL 场景下加 uring_lock 并进入 io_submit_sqes(ctx, to_submit)
  3. io_get_sqe() 从共享 SQ 拉取一个 SQE(用 READ_ONCE 保证稳定读);
  4. io_submit_sqe()
    • io_init_req() 解析 SQE(flags/限制/文件/cred/link/drain 等);
    • 根据 link / force_async 决定 inline issue 或 fallback 到异步;
  5. io_queue_sqe() -> io_issue_sqe()
    • io_op_defs[opcode].issue() 分发到具体模块;
    • 成功后进入完成流程,失败走 async/poll/iowq 兜底;
  6. 批处理结束 io_commit_sqring() 推进 sq.head

实现要点

  • 支持 IORING_SETUP_SUBMIT_ALL:部分 SQE 出错不立即中断整批;
  • 支持 link/hardlink/drain:表达跨请求依赖;
  • 支持 personality:按请求临时切换 cred。

4.3 完成链:io_req_complete_post -> CQ ring

  1. 请求完成后写入 req->cqe
  2. __io_fill_cqe_req() 获取 CQE 槽(优先走缓存 cqe_cached);
  3. io_commit_cqring() 以 release 语义更新 cq.tail
  4. io_cqring_wake() 唤醒 cq_wait 上等待线程;
  5. 如果 CQ 满,进入 overflow 路径并更新 cq_overflow/check_cq

实现要点

  • CQ 写入与 tail 更新严格内存序;
  • 通过 overflow + dropped 标志向用户态传达背压与丢失信息。

5. 执行模型(四种路径)

5.1 inline(最短路径)

  • 提交线程直接 issue(),适用于可立即完成或非阻塞成功的请求。

5.2 task_work defer

  • 将完成或后续动作挂到 task_work,在返回用户态前/合适时机运行。
  • IORING_SETUP_DEFER_TASKRUN 可将本地 work 延后到提交者线程统一处理。

5.3 io-wq worker pool(阻塞慢路径)

  • io-wq.c 提供每 NUMA 节点 io_wqe 池;
  • 分 bounded/unbounded 两类账户;
  • 对可能阻塞的请求转交 worker 执行,避免卡住提交线程。

5.4 SQPOLL / IOPOLL(轮询路径)

  • SQPOLL:专用 io_sq_thread() 轮询 SQ,减少提交 syscall;
  • IOPOLL:适用于支持轮询完成的设备 I/O,请求挂入 iopoll_list 并由轮询收割。

6. 资源管理机制

6.1 固定文件与固定缓冲

  • rsrc.c + filetable.c + kbuf.c 管理注册资源;
  • 固定资源减少每请求 fget/pin 成本,提升高 QPS 稳定性。

6.2 内存记账与限制

  • __io_account_mem()RLIMIT_MEMLOCK 绑定;
  • 同步维护 user->locked_vmmm->pinned_vm,防止无限 pin 页。

6.3 资源异步释放

  • io_rsrc_put_work() 通过 workqueue 回收;
  • 可选给 tag 发送辅助 CQE,通知用户资源释放完成。

7. 并发与内存序设计

关键并发策略:

  • 提交主路径由 uring_lock 串行化;
  • 完成面由 completion_lock + CQ 缓存批量化降低锁开销;
  • ring head/tail 更新使用 smp_store_release / smp_load_acquire
  • 用户共享内存读取关键字段使用 READ_ONCE,避免被用户态并发改写导致重读不一致。

核心目标:在“用户共享内存 + 内核并发执行”模型下保证可见性与一致性。


8. opcode 扩展方法(实现视角)

新增一个 opcode 的标准步骤:

  1. 新增 xxx.c/.h,实现 prep/issue/(cleanup)
  2. opdef.cio_op_defs[] 填入能力位与函数指针;
  3. Makefile 加入目标文件;
  4. 若需要 register 能力、资源或 fdinfo 展示,再接入 io_uring_register / fdinfo 路径。

这套模式让核心调度保持稳定,具体语义在子模块独立演进。


9. 常见问题定位建议

  1. 提交了但没完成

    • sq.head/tailcq.head/tail 是否推进;
    • 检查 cq_overflowsq_dropped 是否增长;
    • 核查 IORING_SETUP_DEFER_TASKRUN 下 task_work 是否被及时运行。
  2. 高负载下延迟抖动

    • 检查是否频繁 fallback 到 io-wq(说明 inline 非阻塞命中率低);
    • 评估固定文件/固定缓冲是否启用;
    • 观察 SQPOLL/IOPOLL 与实际设备能力是否匹配。
  3. 资源注册失败或 ENOMEM

    • 关注 RLIMIT_MEMLOCKpinned_vm、固定缓冲大小;
    • 检查注册参数和索引范围是否越界。
  4. 链式请求行为异常

    • 核对 IOSQE_IO_LINKIOSQE_IO_HARDLINKIOSQE_IO_DRAIN 组合;
    • 关注失败后 REQ_F_FAIL 与 link 断链策略。

10. 一句话总结

io_uring 在该 6.1 内核中的架构本质是:
“共享 ring + opcode 分发表 + 多后端执行引擎(inline/task_work/io-wq/sqpoll)+ 资源注册体系”,通过细粒度并发控制与内存序保证,实现高吞吐、低 syscall 成本的统一异步 I/O 平台。

io_uring 文档索引

io_uring 文档索引

Linux 6.1(RK3588)内核 io_uring 子系统源码分析与原理说明。

总览文档

文档 说明
io_uring异步IO机制与原理详解.md 总览:环模型、syscall、模块划分、RK3588
源码目录与模块索引.md io_uring/ 文件清单、Makefile 映射

功能组专题(原理 + 实现)

编号 文档 源码重点
01 核心接口与环机制与实现详解.md io_uring_setup/enter/registerio_ring_ctx
02 提交与完成路径机制与实现详解.md io_submit_sqesio_issue_sqe、CQE、task_work
03 操作码与opdef分派机制与实现详解.md opdef.crw/fs/net
04 异步执行与SQPOLL机制与实现详解.md io-wq.csqpoll.ctctx.c
05 轮询超时与取消机制与实现详解.md poll.ctimeout.ccancel.cepoll.c
06 资源注册与URING_CMD机制与实现详解.md rsrc.ckbuf.curing_cmd.cfiletable.c
07 RK3588平台关联与使用场景详解.md 配置、性能、块/网络/编解码场景

源码路径

1
2
3
rk3588/kernel-6.1/io_uring/
include/linux/io_uring_types.h
include/uapi/linux/io_uring.h

阅读顺序建议

总览01 核心接口与环02 提交与完成03 操作码04 io-wq / SQPOLL05 poll / timeout06 资源 / URING_CMD07 RK3588

速查

机制 关键入口
创建环 io_uring_setupio_uring_create
提交/收割 io_uring_enterio_submit_sqes / io_cqring_wait
注册资源 io_uring_register__io_uring_register
执行 SQE io_issue_sqeio_op_defs[opcode].issue
阻塞异步 io_queue_iowqio-wq worker
内核轮询 SQ IORING_SETUP_SQPOLL + sqpoll.c
驱动私有命令 IORING_OP_URING_CMD + io_uring_cmd_done

关联文档

  • 块层多队列(与 IOPOLL/URING_CMD):drivers/block、NVMe 驱动
  • 内存锁定:linuxDoc/mmRLIMIT_MEMLOCK、固定缓冲区注册)
  • 网络栈:net.cCONFIG_NET

io_uring/ 源码目录与模块索引

io_uring/ 源码目录与模块索引

源码路径rk3588/kernel-6.1/io_uring/(约 56 个文件)
内核版本:Linux 6.1(RK3588 / ARM64)
文档目录linuxDoc/io_uring/


一、构建与配置

说明
CONFIG_IO_URING init/Kconfig,默认 yselect IO_WQ
CONFIG_IO_WQ 独立对象 io-wq.o,io_uring 异步工作池
块层 部分配置 select IO_URING(如 drivers/block/Kconfig

平台io_uring/ rockchip / RK3588 专用代码。


二、Makefile 对象映射

对象 源文件 职责
io_uring.o io_uring.c 核心:syscall、环、提交/完成、iopoll
opdef.o opdef.c 操作码表 io_op_defs[]
io-wq.o io-wq.c 异步 worker 池(CONFIG_IO_WQ)
sqpoll.o sqpoll.c 内核 SQ 轮询线程
tctx.o tctx.c 每任务 io_uring 上下文
rw.o rw.c READ/WRITE/READV/WRITEV/FIXED 等
poll.o poll.c POLL_ADD/REMOVE/MULTISHOT
timeout.o timeout.c 链式/链接超时
cancel.o cancel.c 异步取消
rsrc.o rsrc.c 文件/缓冲区注册(含 v2)
kbuf.o kbuf.c 提供缓冲区、PBUF_RING
filetable.o filetable.c 固定文件表
uring_cmd.o uring_cmd.c IORING_OP_URING_CMD
net.o net.c send/recv/accept/connect…
fs.o / openclose.o / statx.o / xattr.c 文件系统类 op
sync.o / splice.o / advise.o fsync、mmap 建议、splice
epoll.o epoll.c epoll _ctl/wait
msg_ring.o msg_ring.c 环间消息
notif.o notif.c 通知类辅助
fdinfo.o fdinfo.c /proc fdinfo 导出
nop.o nop.c NOP

头文件(模块内):io_uring.hopdef.hio-wq.hsqpoll.hpoll.hrsrc.hkbuf.huring_cmd.htctx.hrefs.hslist.h 等。


三、核心源文件体量

文件 约行数 说明
io_uring.c ~4200 最大单文件,syscall + 环生命周期
io-wq.c ~1400 worker 池
poll.c ~1000 poll 与 multishot
rw.c ~1000 读写路径
rsrc.c ~1200 注册资源
opdef.c ~550 操作码分发表

四、UAPI 与内核类型

头文件 作用
uapi/linux/io_uring.h SQE/CQE、IORING_OP_*IORING_REGISTER_*
include/linux/io_uring_types.h io_ring_ctxio_kiocbio_rings
include/linux/io_uring.h 驱动 io_uring_cmd API

五、专题文档对照

主题 文档
syscall / 环 01
提交完成 02
操作码 03
io-wq / SQPOLL 04
poll / timeout 05
rsrc / URING_CMD 06
RK3588 07

SysV IPC 公共框架与 ID 管理机制与实现详解

SysV IPC 公共框架与 ID 管理机制与实现详解

源码路径rk3588/kernel-6.1/ipc/util.cutil.h
文档目录linuxDoc/ipc/


目录


一、原理

三类 SysV IPC 共享 同一套标识与权限框架,避免三套重复逻辑:

  • 用户通过 keyftok 生成)或 IPC_PRIVATE 创建对象
  • 内核返回 int id(含 sequence)
  • 对象共性字段在 struct kern_ipc_perm(uid/gid/cuid/cgid、mode、key、seq)

二、实现方式

2.1 struct ipc_ids

成员 作用
ipcs_idr 按 id 索引对象
key_ht rhashtable 按 key 快速查找
rwsem 保护 idr 增删与 proc 遍历
seq 分配下一 sequence

2.2 创建合并逻辑 ipcget

1
2
int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
struct ipc_ops *ops, struct ipc_params *params)
  • ipcget_new:无匹配 key 时 ops->getnewnewary / newque / newseg
  • ipcget_public:存在 key 时权限检查 + more_checks

2.3 ipc_addid / ipc_rmid

  • 分配 idr 槽位,写入 sequence,插入 key 哈希
  • 删除时 ipc_rmid + ipc_rcu_putref 延迟释放(RCU)

2.4 struct ipc_ops

各子系统实现:

回调 信号量 消息 共享内存
getnew newary newque newseg
associate security_sem_associate
more_checks shm_more_checks(size)

三、关键接口

函数 作用
ipc_init_ids 初始化某类 ids
ipc_lock / ipc_unlock 单对象自旋锁
ipcperms 对照 currentipcp->mode
ipc_parse_version IPC_64 / IPC_OLD cmd 解析
kernel_to_ipc64_perm 导出到用户 msqid_ds

ID 上限IPCMNI 32768;CONFIG_SYSVIPC_SYSCTL 可扩展 index 位(ipc_mni_shift)。


四、proc 与热插拔

  • ipc_initproc_mkdir("sysvipc"),各子系统注册 semmsgshm seq_file
  • 内存热插拔 notifier:调整 msgmni 等(低内存缩放)

五、调试

1
2
3
4
ls /proc/sysvipc/
ipcs -a
cat /proc/sys/kernel/sem
cat /proc/sys/kernel/msgmax

附录

符号 文件
ipc_init util.c ~90
ipc_findkey ~172

下一篇02 信号量

信号量机制与实现详解

信号量机制与实现详解

源码路径rk3588/kernel-6.1/ipc/sem.c
文档目录linuxDoc/ipc/


目录


一、原理

System V 信号量信号量数组(semaphore array) 为单位:

  • semget 创建/打开,返回 semid
  • semop / semtimedop 对数组中一个或多个成员做 P/Vsem_opsem_numsem_opsem_flg
  • semctl:GETVAL/SETVAL、GETPID、IPC_RMID、SEM_UNDO

语义:FIFO 排队(非严格防饥饿);支持 原子多操作(同一 semop 内多个 sembuf)。


二、数据结构

结构 说明
struct sem_array kern_ipc_perm,数组 sem[]
struct sem semval、修改者 pid、等待队列
struct sem_queue 阻塞的 semop 请求
struct sem_undo 进程退出时回滚调整(CLONE_SYSVSEM 影响 per-thread/per-process)

三、实现要点(sem.c 文件头注释)

主题 实现
扩展性 数组 独立锁;数组间无全局锁
唤醒 waker 完成全部工作,被唤醒任务可无锁返回(wake_q
update_queue 成功 semop 后扫描等待队列,尽量满足后续操作
UNDO 每进程每数组懒分配 undo 向量,退出时限 SEMVMX
快速路径 sem_lock() 对部分读路径优化(见源码 sem_lock

sysctl(每 ipc_namespace):kernel.sem 四元组 SEMMSL SEMMNS SEMOPM SEMMNI


四、系统调用

syscall 功能
semget 创建/查找
semop semtimedop 超时为 NULL
semtimedop 纳秒级超时
semctl 控制 / 统计 SEM_STAT SEM_INFO

ipc()syscall.c 中转发 SEMOP/SEMGET/SEMCTL


五、调试

1
2
ipcs -s
strace -e semop,semget ./app

常见问题:EIDRM(数组已删)、EAGAINIPC_NOWAIT)、undo 耗尽。


附录

  • 行数:约 2400+(sem.c 为 ipc 最大单文件之一)
    相关01 公共框架

SysV 消息队列机制与实现详解

SysV 消息队列机制与实现详解

源码路径rk3588/kernel-6.1/ipc/msg.cmsgutil.c
文档目录linuxDoc/ipc/


目录


一、原理

消息队列链表 保存变长消息,发送方 拷贝 数据到内核(非零拷贝共享内存):

  • msgget 创建队列
  • msgsnd 入队(可阻塞)
  • msgrcvtype 规则取消息(SEARCH_EQUAL<type 等)
  • msgctl:STAT、SET、RMID、INFO

适合 小消息、多类型 协调;高吞吐场景更倾向 shmsocket


二、数据结构

1
2
3
4
5
6
7
struct msg_queue {
struct kern_ipc_perm q_perm;
...
struct list_head q_messages;
struct list_head q_receivers;
struct list_head q_senders;
};
结构 作用
msg_msg 消息头 + 内联或分页数据(msgutil.c
msg_receiver 阻塞接收者,r_msg 无锁完成路径
msg_sender 阻塞发送者

三、实现要点

3.1 MSG_BARRIER(与 mqueue 类似)

接收方被唤醒时,r_msgrelease/acquire 语义设置,使 返回路径可不持锁,降低 contention。

3.2 限额(每 namespace)

参数 sysctl 典型名 含义
msg_ctlmax msgmax 单条消息最大字节
msg_ctlmnb msgmnb 队列总字节上限
msg_ctlmni msgmni 系统队列数上限

percpu_msg_bytes / percpu_msg_hdrs 统计用量;内存热插拔可触发 auto_msgmni 重算。

3.3 安全

security_msg_queue_*audit 挂钩在关联与操作时。


四、msgutil 消息体

  • alloc_msg / load_msg / store_msg:按页链式 msg_msgseg
  • init_ipc_ns:全局初始命名空间(无 IPC_NS 时仍需要)
  • DEFINE_SPINLOCK(mq_lock):与 POSIX mqueue 共享(注释说明单文件编译场景)

五、系统调用与限额

syscall 说明
msgget
msgsnd / msgrcv 支持 IPC_NOWAIT
msgctl 含 64 位 msqid_ds

附录

相关05 POSIX mqueue(不同 API,同属 IPC 命名空间)

共享内存机制与实现详解

共享内存机制与实现详解

源码路径rk3588/kernel-6.1/ipc/shm.c
文档目录linuxDoc/ipc/


目录


一、原理

SysV 共享内存同一物理页 映射到多个进程地址空间:

  • shmget:按 key 创建段,指定 size(只增不减)
  • shmat:attach,指定地址/标志(SHM_RDONLY 等)
  • shmdt:detach
  • shmctl:IPC_RMID、STAT、锁定/解锁(SHM_LOCK)等

自动同步读写,需应用自配信号量或其它同步。


二、数据结构

结构 说明
struct shmid_kernel kern_ipc_perm + shm_file + shm_nattch + 段大小
struct shm_file_data 关联 shm id、ns、vm 列表

shm_ids(ns)ipc_namespace->ids[IPC_SHM_IDS]


三、实现要点

3.1 文件与 VMA

  • 段对应 特殊 shmem 文件shm_file_operations
  • shmatdo_shmat:创建 mmap VMA,shm_vm_opsshm_open/shm_close/shm_fault
  • 支持 HugeTLB 变体(shm_file_operations_huge

3.2 生命周期

  • shm_nattch 计数;IPC_RMID 后若 attach 仍为 0 才真正销毁
  • shm_rmid_forced sysctl:强制 RMID 行为(孤儿段清理 shm_destroy_orphaned
  • 进程退出:exit_shm 遍历 detach

3.3 限额

字段 sysctl
shm_ctlmax shmmax 单段最大
shm_ctlall shmall 页总数上限
shm_ctlmni shmmni 段数量

shm_tot 跟踪已用页。


四、与内存子系统交互

  • 实际页面由 shmem/tmpfs 回退机制分配(见 linuxDoc/mm 中 shmem)
  • shm_fault:缺页填充
  • mempolicyshm_set_policy / shm_get_policy
  • RK3588 编解码:大缓冲区更常用 DMA-BUF / ion;SysV shm 多见于遗留 IPC

五、系统调用

syscall 说明
shmget ksys_shmget
shmat / shmdt 兼容 COMPAT 地址
shmctl old_shmctl 兼容旧结构

附录

相关01 ID 管理linuxDoc/mm

POSIX 消息队列机制与实现详解

POSIX 消息队列机制与实现详解

源码路径rk3588/kernel-6.1/ipc/mqueue.cmq_sysctl.c
文档目录linuxDoc/ipc/


目录


一、原理

POSIX 消息队列路径名 标识(挂载 mqueue 文件系统),每条消息带 优先级

  • mq_open 创建/打开队列(O_CREAT
  • mq_timedsend / mq_timedreceive
  • mq_notify:异步通知(signotify 或 线程唤醒
  • mq_getattr / mq_setattr:队列深度、消息大小等

依赖 CONFIG_POSIX_MQUEUE 且 Kconfig 要求 depends on NET(历史依赖,实现使用 netlink 相关基础设施做通知)。


二、与 SysV 消息队列对比

维度 SysV (msg.c) POSIX (mqueue.c)
标识 key / id 路径名
优先级 type 字段 显式 unsigned prio
接口 msgsnd/msgrcv mq_*
可见性 ipcs ls /dev/mqueue(挂载点可配置)
实现文件 msg.c VFS + inode

三、实现要点

3.1 核心结构(mqueue.c

  • struct mqueue_inode_info:红黑树按 priority 组织消息、等待队列
  • posix_msg_tree_node:每优先级一条链表
  • 锁:info->lock;唤醒用 wake_q + MQ_BARRIER(注释详述 UAF 竞态防护)

3.2 命名空间

  • mq_init_ns:挂载 mqueue、初始化 mq_queues_max
  • mq_put_mnt:释放 namespace 时卸载

3.3 sysctl(mq_sysctl.c

典型 fs.mqueue.*queues_maxmsgsize_maxmsg_max 等( per ipc_namespace)。


四、文件系统与系统调用

syscall 功能
mq_open / mq_unlink 创建/删除队列 inode
mq_timedsend / mq_timedreceive 带超时收发
mq_notify 注册 sigevent
mq_getsetattr 属性

msgutil.o 与 SysV 共用:全局 init_ipc_nsmq_lock


五、调试

1
2
3
mount -t mqueue none /dev/mqueue   # 若未挂载
ls /dev/mqueue
cat /proc/sys/fs/mqueue/*

附录

相关06 命名空间

命名空间、sysctl 与兼容层机制与实现详解

命名空间、sysctl 与兼容层机制与实现详解

源码路径rk3588/kernel-6.1/ipc/namespace.cipc_sysctl.cmq_sysctl.ccompat.csyscall.c
文档目录linuxDoc/ipc/


目录


一、IPC 命名空间

1.1 创建与克隆

1
2
3
4
5
6
7
struct ipc_namespace *copy_ipcs(unsigned long flags,
struct user_namespace *user_ns, struct ipc_namespace *ns)
{
if (!(flags & CLONE_NEWIPC))
return get_ipc_ns(ns);
return create_ipc_ns(user_ns, ns);
}

create_ipc_ns 顺序:mq_init_ns → sysctl → msg_init_nssem_init_nsshm_init_ns

1.2 销毁

  • 引用计数归零时删除所有 SysV 对象、mqueue 挂载
  • put_ipc_ns / free_ipc_ns:与 pid namespace、user namespace 协同

1.3 配置

  • CONFIG_IPC_NS:默认 y(需 SYSVIPC 或 POSIX_MQUEUE)
  • inc_ipc_namespacesucount 限制每用户 NS 数量

二、sysctl

2.1 ipc_sysctl.c(SysV)

procname 绑定字段 作用
shmmax / shmall / shmmni shm 共享内存限额
msgmax / msgmni / msgmnb msg 消息队列
sem sem_ctls[4] SEMMSL 等
shm_rmid_forced 强制清理孤儿 shm

ipc_mni / ipc_mni_shift:扩展 IPC ID index 位数(需 SYSVIPC_SYSCTL)。

2.2 mq_sysctl.c

每 NS 的 fs.mqueue* 限额,与 mq_queues_count 协同。


三、syscall 与 compat

3.1 旧 ipc() 多路复用(syscall.c

__ARCH_WANT_SYS_IPC 的架构上,SYSCALL_DEFINE6(ipc)call 分派 SEM/MSG/SHM 子命令;ARM64 通常直接实现独立 syscall,此文件可能不参与链接。

3.2 compat.c / CONFIG_SYSVIPC_COMPAT

  • 32 位用户态:old_msgctlold_semctlcompat msgrcv
  • semtimedop_time32mq_*_time32 在各自文件

四、init_ipc_ns

msgutil.c

1
struct ipc_namespace init_ipc_ns = { ... };

初始命名空间;容器创建新 NS 时复制/新建限额默认值。


附录

操作 用户命令
新 IPC NS unshare --ipc / docker run
查看 NS /proc/<pid>/ns/ipc

相关07 RK3588