从零写 OS 内核-第二十五篇:Unix 域套接字 —— 实现进程间通信(IPC)的基石

“Display Server 与 Client 需要高效通信,但管道只能单向、无结构。 今天,我们实现 Unix 域套接字(AF_UNIX),让进程间通信像操作文件一样自然!”

在上一篇中,我们构建了 Display Server + Client 架构, 但 IPC 通道是简化的管道(pipe),存在明显局限:

仅支持单向通信
无连接概念

→ 无法区分多个 Client
无文件描述符传递

→ 无法共享内存句柄

真正的 IPC 需要 Unix 域套接字(Unix Domain Socket) : ✅ 双向通信 ✅ 支持 SOCK_STREAM(流式)和 SOCK_DGRAM(报文) ✅ 可传递文件描述符 (如共享内存、设备句柄) ✅ 通过路径名寻址 (如 /tmp/display.sock )

今天,我们就来: ✅ 设计套接字 VFS 抽象层 ✅ 实现 AF_UNIX 协议族 ✅ 支持 connect/listen/accept/send/recv ✅ 演示文件描述符传递

让你的 OS 拥有 工业级 IPC 能力 !


🧩 一、为什么需要 Unix 域套接字?

管道(Pipe)的局限:

问题 后果
单向通信 需要两个管道实现双向
无连接标识 Server 无法区分多个 Client
无路径名 只能父子进程通信
无 FD 传递 无法共享资源句柄

Unix 域套接字的优势:

路径名寻址


/var/run/display.sock
全双工

:单个 socket 支持双向
连接导向


accept()
返回新 socket 代表一个连接
FD 传递

:通过
sendmsg
传递文件描述符

💡 D-Bus、Wayland、X11 全部基于 Unix 域套接字 !


🏗️ 二、套接字 VFS 抽象层

套接字在 VFS 中表现为 特殊文件 ,但操作通过 socket 系统调用。

  1. 套接字 inode

  2. 套接字文件操作

  3. 系统调用对接

🔑 socket() 返回的 fd 本质是一个特殊文件 !


🔌 三、AF_UNIX 协议实现

  1. 套接字结构

  2. bind:绑定路径名

  3. listen:监听连接

  4. accept:接受连接

  5. connect:连接 Server


💬 四、数据传输:send/recv

  1. 内核消息队列

  2. sendmsg(支持 FD 传递)

  3. recvmsg(接收 FD)

🔑 FD 传递的本质:将 file 对象从一个进程的 fd_table 复制到另一个进程 !


🧪 五、测试:Display Server 与 Client 通信

  1. Server 创建 socket

  2. Client 连接并传递 shm

  3. Server 接收 shm_fd

✅ Client 通过 socket 安全传递共享内存句柄 !


⚠️ 六、关键实现细节

  1. 引用计数

    file

    对象必须有引用计数,FD 传递时增加
    进程退出时自动关闭 FD

  2. 同步保护

    接收/发送队列需自旋锁保护
    避免多核并发访问冲突

  3. 路径名管理

    bind

    时创建 VFS socket 文件
    close

    时删除(或引用计数为 0 时删除)

  4. 连接状态机

    SS_UNCONNECTED


    SS_CONNECTING

    SS_CONNECTED

💡 Linux 的 af_unix.c 是更完整的实现参考 !


💬 写在最后

Unix 域套接字是 IPC 的 瑞士军刀 。 它统一了文件与网络接口, 让进程通信变得简单而强大。

今天你传递的第一个文件描述符, 正是 D-Bus、Wayland 等现代 IPC 机制的基石。

🌟 最好的抽象,是让用户忘记通信的存在。


📬 动手挑战 : 实现 SOCK_DGRAM 模式,并测试无连接通信。 欢迎在评论区分享你的 IPC 性能对比!

👇 下一篇你想看: 输入事件处理与窗口管理 ,还是 字体渲染与文本显示 ?


#操作系统 #内核开发 #Unix域套接字 #IPC #进程间通信 #文件描述符传递 #从零开始


📢 彩蛋 :关注后回复关键词 “socket” ,获取:
完整 AF_UNIX 实现代码(含 bind/connect/accept)
sendmsg/recvmsg 与 FD 传递模板
Display Server/Client 通信集成示例

最后修改: 2026年7月1日

作者

评论

发表评论

您的邮箱地址不会被公开。