从零写 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 系统调用。
- 套接字 inode
-
套接字文件操作
-
系统调用对接
🔑 socket() 返回的 fd 本质是一个特殊文件 !
🔌 三、AF_UNIX 协议实现
- 套接字结构
-
bind:绑定路径名
-
listen:监听连接
-
accept:接受连接
-
connect:连接 Server
💬 四、数据传输:send/recv
-
内核消息队列
-
sendmsg(支持 FD 传递)
-
recvmsg(接收 FD)
🔑 FD 传递的本质:将 file 对象从一个进程的 fd_table 复制到另一个进程 !
🧪 五、测试:Display Server 与 Client 通信
- Server 创建 socket
-
Client 连接并传递 shm
-
Server 接收 shm_fd
✅ Client 通过 socket 安全传递共享内存句柄 !
⚠️ 六、关键实现细节
- 引用计数
file
对象必须有引用计数,FD 传递时增加
进程退出时自动关闭 FD -
同步保护
接收/发送队列需自旋锁保护
避免多核并发访问冲突 -
路径名管理
bind
时创建 VFS socket 文件
close时删除(或引用计数为 0 时删除)
-
连接状态机
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 通信集成示例
评论