Unix Domain Socket和eventfd

在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 Socket
        listen 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 pair

    char buf[128];
    write(sock_pair[0], "Hello from sock0", 16);       // 写入 sock0
    read(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] 和 efd
    while (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)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/980644.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

实验:k8s+keepalived+nginx+iptables

1、创建两个nginx的pod&#xff0c;app都是nginx nginx1 nginx2 2、创建两个的pod的service 3、配置两台keepalived的调度器和nginx七层反向代理&#xff0c;VIP设置192.168.254.110 keepalived调度器master keepalived调度器backup 两台调度器都配置nginx七层反向代理&#…

【Cadence仿真学习笔记】ADS Dynamic Link报错model is reserved的解决办法

首先创建好原理图 创建symbol 在library manager下就会出现symbol了 在Cadence的CIW窗口中运行ADS dynamic link 打开ADS后&#xff0c;创建对应的cellview 加入控件OPTIONS 加入网表netlist 这个时候的Netlist没有路径 点击加载symbol 把原来的netlist include删掉…

【星云 Orbit • STM32F4】06. 串口密码:USART 数据传递

1. 引言 STM32F407是一款高性能的微控制器&#xff0c;具有丰富的外设和强大的处理能力。串口&#xff08;USART&#xff09;是STM32F407的重要外设之一&#xff0c;广泛应用于数据通信、调试和控制等领域。本教程旨在帮助小白从零开始&#xff0c;手动配置STM32F407的串口功能…

Win32 C++ 电源计划操作

CPowerCfgUtils.h #pragma once#include <Windows.h> #include <powrprof.h>// https://learn.microsoft.com/zh-cn/windows/win32/api/powrprof/?sourcerecommendations//节能 //DEFINE_GUID(GUID_MAX_POWER_SAVINGS, 0xA1841308, 0x3541, 0x4FAB, 0xBC, 0x81, …

MySQL—使用binlog日志恢复数据

一、binlog日志恢复数据简介 在 MySQL 中&#xff0c;使用二进制日志&#xff08;binlog&#xff09;恢复数据是一种常见的用于故障恢复或数据找回的方法。以下是详细的使用步骤&#xff1a; 确认 binlog 已启用&#xff1a;首先需要确认 MySQL 服务器已经启用了二进制日志功…

基于springboot+vue实现的宠物救助及领养平台(源码+L文+ppt)43-21

摘 要 宠物救助及领养平台是一个专注于宠物保护和幸福的在线平台。它致力于连接那些需要帮助的宠物与愿意给予它们关爱的家庭。通过这个平台&#xff0c;人们可以报告丢失的宠物、寻求救助资源&#xff0c;以及浏览可领养的宠物信息。该平台不仅提供了一个渠道&#xff0c;让…

人大金仓国产数据库与PostgreSQL

一、简介 在前面项目中&#xff0c;我们使用若依前后端分离整合人大金仓&#xff0c;在后续开发过程中&#xff0c;我们经常因为各种”不适配“问题&#xff0c;但可以感觉得到大部分问题&#xff0c;将人大金仓视为postgreSQL就能去解决大部分问题。据了解&#xff0c;Kingba…

【Java分布式】Nacos注册中心

Nacos注册中心 SpringCloudAlibaba 也推出了一个名为 Nacos 的注册中心&#xff0c;相比 Eureka 功能更加丰富&#xff0c;在国内受欢迎程度较高。 官网&#xff1a;https://nacos.io/zh-cn/ 集群 Nacos就将同一机房内的实例划分为一个集群&#xff0c;一个服务可以包含多个集…

派可数据BI接入DeepSeek,开启智能数据分析新纪元

派可数据BI产品完成接入DeepSeek&#xff0c;此次接入标志着派可数据BI在智能数据分析领域迈出了重要一步&#xff0c;将为用户带来更智能、更高效、更便捷的数据分析体验。 派可数据BI作为国内领先的商业智能解决方案提供商&#xff0c;一直致力于为用户提供高效、稳定易扩展…

【漫话机器学习系列】110.线性可分(Linearly Separable)

线性可分与线性不可分的概念详解 1. 引言 在机器学习和模式识别领域&#xff0c;分类问题是一个重要的研究方向。在分类任务中&#xff0c;我们通常需要将不同类别的数据点分开&#xff0c;而如何进行分割是一个关键问题。线性可分&#xff08;Linearly Separable&#xff09…

架构师面试(九):缓存一致性

问题 关于【数据库和缓存】一致性&#xff0c;下面哪几项是在线上生产环境中相对合理的处理方式&#xff1f; A. 对于查询操作&#xff0c;先查缓存&#xff0c;如果为空则查 DB&#xff0c;然后将数据带入缓存&#xff1b; B. 对于插入操作&#xff0c;只写 DB 即可&#…

LearnOpenGL之Shader编程用算法绘画

———————————————————— 前序 ——————————————————— AndroidLearnOpenGL是本博主自己实现的LearnOpenGL练习集合&#xff1a; Github地址&#xff1a;GitHub - wangyongyao1989/AndroidLearnOpenGL: OpenGL基础及运用 系列文章&#xff…

基于 Flink CDC YAML 的 MySQL 到 Kafka 流式数据集成

本教程的演示都将在 Flink CDC CLI 中进行&#xff0c;无需一行 Java/Scala 代码&#xff0c;也无需安装 IDE。 这篇教程将展示如何基于 Flink CDC YAML 快速构建 MySQL 到 Kafka 的 Streaming ELT 作业&#xff0c;包含整库同步、表结构变更同步演示和关键参数介绍。 准备阶段…

【Maven】基于IDEA进行Maven工程的创建、构建

文章目录 一、基于IDEA创建Maven工程1. 概念梳理Maven工程的GAVP2. Idea构建Maven Java SE工程3. Idea构建Maven Java Web工程3.1 创建一个maven的javase工程3.2 修改pom.xml文件打包方式3.3 设置web资源路径和web.xml路径 4. Maven工程项目结构说明 二、基于IDEA进行Maven工程…

计算机毕业设计SpringBoot+Vue.js在线课程管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

【爬虫基础】第二部分 爬虫基础理论 P3/3

上节内容回顾&#xff1a;【爬虫基础】第一部分 网络通讯 P1/3-CSDN博客 【爬虫基础】第一部分 网络通讯-Socket套接字 P2/3-CSDN博客 【爬虫基础】第一部分 网络通讯-编程 P3/3-CSDN博客 【爬虫基础】第二部分 爬虫基础理论 P1/3-CSDN博客 【爬虫基础】第二部分 爬虫基础理论…

【子网掩码计算器:Python + Tkinter 实现】

子网掩码计算器&#xff1a;Python Tkinter 实现 引言代码功能概述代码实现思路1. 界面设计2. 功能实现3. 事件处理 子网掩码计算器实现步骤1. 导入必要的库2. 定义主窗口类 SubnetCalculatorApp3. 创建菜单栏4. 创建界面组件5. 判断 IP 地址类别6. 计算子网信息7. 其他功能函…

【第十节】C++设计模式(结构型模式)-Flyweight( 享元)模式

目录 一、问题背景 二、模式选择 三、代码实现 四、总结讨论 一、问题背景 享元模式&#xff08;Flyweight Pattern&#xff09;在对象存储优化中的应用 在面向对象系统的设计与实现中&#xff0c;创建对象是最常见的操作之一。然而&#xff0c;如果一个应用程序使用了过多…

macOS - 使用 tmux

文章目录 安装 tmux使用更多快捷键说明 安装 tmux brew install tmux使用 在终端输入 tmux 进入 tmux 界面&#xff0c;然后 输入 Control Option B 进入交互模式 输入 % 左右分栏&#xff0c;" 上下分割 上一个窗格&#xff1a;{&#xff0c;下一个&#xff1a;} PS…

【洛谷贪心算法题】P1094纪念品分组

该题运用贪心算法&#xff0c;核心思想是在每次分组时&#xff0c;尽可能让价格较小和较大的纪念品组合在一起&#xff0c;以达到最少分组的目的。 【算法思路】 输入处理&#xff1a;首先读取纪念品的数量n和价格上限w&#xff0c;然后依次读取每件纪念品的价格&#xff0c;…