Unix Domain Socket和eventfd

devtools/2025/3/6 17:22:50/

在Linux开发中,Unix Domain Socketeventfd是两种不同的通信机制,它们的设计目标和适用场景有显著差异。以下分点解释并配合示例说明:


一、Unix Domain Socket(UDS)

1. 是什么?
  • 一种**本地进程间通信(IPC)**机制,基于文件系统路径而非网络端口
  • 协议族为AF_UNIX(而非网络Socket的AF_INET/AF_INET6
2. 核心特点
  • 高性能:数据直接在内核缓冲区传递,无需经过网络协议栈
  • 支持多种通信模式:流式(SOCK_STREAM,类似TCP)、数据报(SOCK_DGRAM,类似UDP)和可靠数据报(SOCK_SEQPACKET
  • 权限控制:通过文件系统权限(chmod)控制访问
  • 传递文件描述符:可通过sendmsg发送文件描述符(其他IPC机制难以实现)
3. 典型场景
  • Docker守护进程/var/run/docker.sock
  • 数据库本地连接:MySQL客户端通过/var/run/mysqld/mysqld.sock连接本地服务
  • X Window系统:GUI应用与X服务器的通信
  • Systemd服务:通过/run/systemd/下的socket文件通信
4. 代码片段
// 服务端
struct sockaddr_un addr = {.sun_family = AF_UNIX};
strcpy(addr.sun_path, "/tmp/mysocket");
bind(sock, (struct sockaddr*)&addr, sizeof(addr));

二、eventfd

1. 是什么?
  • 一个轻量级事件通知机制,本质是一个内核维护的64位计数器
  • 通过eventfd()系统调用创建,返回一个文件描述符
2. 核心特点
  • 极低开销:适合高频事件通知(如线程间唤醒)
  • 与epoll集成:可直接加入事件循环监听
  • 原子操作:读/写操作是原子的,线程安全
  • 跨进程可用:通过fork或传递fd给其他进程
3. 典型场景
  • 线程池唤醒:主线程通过写eventfd通知工作线程有新任务
  • 协程调度:如Golang的runtime用类似机制唤醒阻塞的goroutine
  • 信号处理:将信号转换为eventfd事件,避免在信号处理函数中执行复杂逻辑
  • IO多路复用集成:与epoll结合实现高效事件驱动架构
4. 代码片段
int efd = eventfd(0, EFD_NONBLOCK); // 创建eventfd
write(efd, &(uint64_t){1}, sizeof(uint64_t)); // 发送事件
read(efd, &counter, sizeof(uint64_t)); // 接收事件

三、Unix Socket vs TCP/UDP Socket

特性Unix Domain SocketTCP/UDP Socket
通信范围同一主机跨网络
地址形式文件路径(如/tmp/foo.sockIP地址+端口(如127.0.0.1:8080
协议开销无网络协议栈处理需要处理TCP握手/重传等
性能比TCP快2倍以上(实测)受网络延迟和带宽限制
权限控制文件系统权限依赖网络防火墙
数据边界保留流式/数据报均保留TCP是流式无边界,UDP有边界
示例对比
  1. Redis客户端连接

    • 远程连接:redis-cli -h 192.168.1.100 -p 6379(TCP)
    • 本地连接:redis-cli -s /tmp/redis.sock(UDS)
  2. Nginx本地配置

    server {listen 80;                  # TCP Socketlisten unix:/var/run/nginx.sock; # Unix Socket
    }
    

四、组合使用案例

场景:构建一个高性能本地服务

  1. 使用Unix Socket处理客户端请求(高吞吐)
  2. 使用eventfd在服务内部线程间传递事件(低延迟)
  3. 用epoll同时监听UDS和eventfd,实现统一事件循环
// 伪代码示例
int uds_fd = create_unix_socket("/tmp/service.sock");
int efd = eventfd(0, EFD_NONBLOCK);struct epoll_event events[2];
epoll_ctl(epfd, EPOLL_CTL_ADD, uds_fd, &(struct epoll_event){.events=EPOLLIN});
epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &(struct epoll_event){.events=EPOLLIN});while(1) {int n = epoll_wait(epfd, events, 2, -1);for (每个就绪事件) {if (事件来自uds_fd) 处理客户端请求();if (事件来自efd) 处理内部事件();}
}

总结选择依据:

  • 需要跨主机通信 → TCP/UDP Socket
  • 本地高性能IPC → Unix Domain Socket
  • 轻量级事件通知 → eventfd
  • 混合场景 → UDS + eventfd + epoll组合

在 Linux 开发中,Socket Pair 是一种特殊的进程间通信(IPC)机制,与 Unix Domain Socket (UDS)TCP/UDP Socketeventfd 有显著区别。以下是它们的核心差异、使用场景和实际示例:


1. Socket Pair 是什么?

  • 定义:通过 socketpair() 系统调用创建的一对已连接的匿名 Unix Domain Socket
  • 特点
    • 无需绑定文件路径:直接创建一对已连接的 socket,没有文件系统路径。
    • 双向通信:两个 socket 可以互相读写(类似全双工管道)。
    • 匿名性:仅限同一进程或父子进程间使用(无法被无关进程访问)。
    • 支持多种模式:流式(SOCK_STREAM)或数据报(SOCK_DGRAM)。
示例代码
#include <sys/socket.h>
#include <stdio.h>int main() {int sock_pair[2];socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair); // 创建 socket pairchar buf[128];write(sock_pair[0], "Hello from sock0", 16);       // 写入 sock0read(sock_pair[1], buf, sizeof(buf));            // 从 sock1 读取printf("Received: %s\n", buf);                   // 输出 "Hello from sock0"close(sock_pair[0]);close(sock_pair[1]);return 0;
}

2. Socket Pair 与其他通信机制的区别

对比 Unix Domain Socket (UDS)
特性Socket PairUnix Domain Socket
地址绑定匿名,无需文件路径需绑定文件路径(如 /tmp/foo.sock
可见性仅限创建进程及其子进程所有有权限访问文件的进程
使用场景父子进程或线程间通信任意进程间通信(需共享路径)
性能更高(无需文件系统操作)高(但需文件路径管理)
对比 TCP/UDP Socket
特性Socket PairTCP/UDP Socket
通信范围同一主机,同一进程或父子进程跨网络或本机(需网络协议栈)
地址形式无地址(匿名)IP地址 + 端口
协议开销无网络协议栈开销需处理 TCP 握手、UDP 不可靠性等
对比 eventfd
特性Socket Paireventfd
通信方向双向(支持数据收发)单向(仅事件通知,无数据内容)
数据类型任意字节流或数据报64位计数器(仅数值增减)
典型用途进程/线程间数据交换事件通知(如唤醒线程池)

3. Socket Pair 的典型使用场景

场景 1:父子进程通信

父进程创建 socket pair,fork 子进程后,父子各关闭一个 socket,实现双向通信:

int sock_pair[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair);if (fork() == 0) {  // 子进程close(sock_pair[0]);  // 关闭父进程端write(sock_pair[1], "Child message", 13);
} else {            // 父进程close(sock_pair[1]);  // 关闭子进程端read(sock_pair[0], buf, sizeof(buf));
}
场景 2:线程间通信

多个线程共享同一 socket pair,实现高效数据传递(需注意线程同步)。

场景 3:替代管道(Pipe)

Socket pair 比传统管道更灵活:

  • 管道是单向的,socket pair 是双向的。
  • Socket pair 支持数据报模式(SOCK_DGRAM)。

4. 组合使用案例

需求:构建一个多进程服务,主进程通过 socket pair 与子进程通信,同时使用 eventfd 通知事件。

// 主进程
int sock_pair[2];
socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair);int efd = eventfd(0, EFD_NONBLOCK);if (fork() == 0) {  // 子进程close(sock_pair[0]);// 监听 sock_pair[1] 和 efdwhile (1) {// 通过 sock_pair[1] 与主进程交换数据// 通过 eventfd 接收事件通知}
} else {            // 主进程close(sock_pair[1]);write(sock_pair[0], "Task data", 9);  // 发送数据write(efd, &(uint64_t){1}, 8);       // 发送事件
}

5. 总结:如何选择?

  • 需要跨网络通信TCP/UDP Socket
  • 本地任意进程间通信Unix Domain Socket(需文件路径)。
  • 父子进程或线程间高效双向通信Socket Pair(匿名,无需文件路径)。
  • 轻量级事件通知eventfd(无数据内容,仅计数器)。
  • 混合场景 → 组合使用(如 Socket Pair + eventfd + epoll)。

http://www.ppmy.cn/devtools/165041.html

相关文章

【数据库】关系代数

关系代数 一、关系代数的概念二、关系代数的运算2.1 并、差、交2.2 投影、选择2.3 笛卡尔积2.4 连接2.5 重命名2.6 优先级 一、关系代数的概念 关系代数是一种抽象的数据查询语言用对关系的运算来表达查询 运算对象&#xff1a;关系运算符&#xff1a;4类运算结果&#xff1a;…

大白话html第五章HTML5 新增表单元素和属性

大白话html第五章HTML5 新增表单元素和属性 HTML5 给表单带来了很多新的小伙伴&#xff0c;让我们收集用户信息变得更方便、更智能。 新增表单元素 <input type"date">&#xff1a;这个就像一个自带日历的小框框&#xff0c;用户可以直接在里面选择日期&…

11 Oracle Golden Gate 高可用解决方案:Golden Gate 助力企业保障业务连续性

文章目录 Oracle Golden Gate 高可用解决方案&#xff1a;Golden Gate 助力企业保障业务连续性一、Oracle Golden Gate基本概念二、设计异地灾备策略2.1 需求分析2.2 网络规划2.3 部署架构 三、实施异地灾备策略3.1 环境准备3.2 配置Golden Gate3.3 验证与测试 四、数据保护策略…

Mac mini M4安装nvm 和node

先要安装Homebrew&#xff08;如果尚未安装&#xff09;。在终端中输入以下命令&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 根据提示操作完成Homebrew的安装。 安装nvm。在终端中输入以下命令&#xf…

Docker 部署开源项目HivisionIDPhotos详细教程

本章教程主要介绍如何在Docker上部署开源项目HivisionIDPhotos。 一、HivisionIDPhotos简介 HivisionIDPhoto 旨在开发一种实用、系统性的证件照智能制作算法。 它利用一套完善的AI模型工作流程,实现对多种用户拍照场景的识别、抠图与证件照生成。 HivisionIDPhoto 可以做到:…

安全见闻5,6

人工智能篇 人工智能目前处于高数发展阶段,所涉及的安全问题也很多 ai所收集的数据有泄露的风险(数据安全) ai进行工作的时候可能因为收集的恶意信息而产生错误(对抗攻击) ai模型被逆向窃取的风险,涉及到知识产权被侵犯的问题 ai被用作与恶意网络攻击的风险 同时要搞好ai…

iOS实现一个强大的本地状态记录容器

我们开发中经常会遇到这样的场景&#xff0c;就是我们客户端用户进行了某个操作&#xff0c;这个操作影响了数据的状态&#xff0c;但是我们又不方便重新请求一次数据&#xff0c; 这个时候&#xff0c;就需要我们记录一下本地状态在内存中&#xff0c;随着业务越来越复杂&…

stm32week5

stm32学习 二.外设 14.串口发送数据包 数据包的定义&#xff1a; HEX数据包(以0xFF为包头&#xff0c;0xFE为包尾&#xff0c;实际上可自定义)&#xff1a; 固定包长&#xff0c;含包头包尾可变包长&#xff0c;含包头包尾 对于数据中不会出现包头包尾的数据可以用可变包长…