嵌入式Linux网络编程:UNIX Domain Socket进程间通信(IPC)
嵌入式Linux网络编程:UNIX Domain Socket进程间通信(IPC)
【本文代码已在Linux平台验证通过】
一、UNIX Domain Socket核心优势
1.1 本地IPC方案对比
| 特性 | UNIX Domain Socket | 管道(Pipe) | 消息队列(Message Queue) | 共享内存(Shared Memory) |
|---|---|---|---|---|
| 跨进程通信 | ✔️ | ✔️ | ✔️ | ✔️ |
| 双向通信 | ✔️ | ❌(半双工) | ✔️ | ✔️ |
| 支持字节流/数据报 | ✔️(SOCK_STREAM/DGRAM) | ❌ | ❌ | ❌ |
| 传输效率 | ★★★★★ | ★★★ | ★★★★ | ★★★★★★ |
| 资源占用 | 低 | 低 | 中 | 高 |
二、UNIX Domain Socket核心原理
2.1 地址结构
struct sockaddr_un {sa_family_t sun_family; // AF_UNIXchar sun_path[108]; // 套接字文件路径(如/tmp/my_socket)
};
2.2 通信流程
三、UNIX Domain Socket服务端实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>#define SOCKET_PATH "/tmp/unix_socket_example" // 套接字文件路径
#define BUFFER_SIZE 128int main() {int server_fd, client_fd;struct sockaddr_un serv_addr, cli_addr;socklen_t cli_len = sizeof(cli_addr);char buffer[BUFFER_SIZE];// 1. 创建Unix域流式套接字if ((server_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {perror("socket创建失败");exit(EXIT_FAILURE);}// 2. 配置地址结构memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sun_family = AF_UNIX;strncpy(serv_addr.sun_path, SOCKET_PATH, sizeof(serv_addr.sun_path)-1);// 3. 确保文件不存在unlink(SOCKET_PATH);// 4. 绑定套接字if (bind(server_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {perror("绑定失败");close(server_fd);exit(EXIT_FAILURE);}// 5. 设置监听队列(最大5个等待连接)if (listen(server_fd, 5) == -1) {perror("监听失败");close(server_fd);exit(EXIT_FAILURE);}printf("服务端已启动,等待客户端连接...\n");// 6. 接受客户端连接if ((client_fd = accept(server_fd, (struct sockaddr*)&cli_addr, &cli_len)) == -1) {perror("接受连接失败");close(server_fd);exit(EXIT_FAILURE);}printf("客户端已连接: %s\n", serv_addr.sun_path);// 7. 通信循环while (1) {ssize_t num_bytes = recv(client_fd, buffer, BUFFER_SIZE, 0);if (num_bytes == -1) {perror("接收错误");break;} else if (num_bytes == 0) {printf("客户端断开连接\n");break;}buffer[num_bytes] = '\0';printf("收到消息: %s\n", buffer);// 构造响应char reply[BUFFER_SIZE];snprintf(reply, sizeof(reply), "服务端已接收 %zd 字节", num_bytes);if (send(client_fd, reply, strlen(reply), 0) == -1) {perror("发送失败");break;}}// 8. 清理资源close(client_fd);close(server_fd);unlink(SOCKET_PATH); // 删除套接字文件return 0;
}
四、UNIX Domain Socket客户端实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>#define SOCKET_PATH "/tmp/unix_socket_example"
#define BUFFER_SIZE 128int main() {int sockfd;struct sockaddr_un serv_addr;char buffer[BUFFER_SIZE];// 1. 创建套接字if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {perror("socket创建失败");exit(EXIT_FAILURE);}// 2. 配置服务端地址memset(&serv_addr, 0, sizeof(serv_addr));serv_addr.sun_family = AF_UNIX;strncpy(serv_addr.sun_path, SOCKET_PATH, sizeof(serv_addr.sun_path)-1);// 3. 连接服务端if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {perror("连接失败");close(sockfd);exit(EXIT_FAILURE);}printf("已连接到服务端\n");// 4. 通信循环while (1) {printf("输入消息(输入exit退出): ");fgets(buffer, BUFFER_SIZE, stdin);buffer[strcspn(buffer, "\n")] = '\0';if (strcmp(buffer, "exit") == 0) break;// 发送数据if (send(sockfd, buffer, strlen(buffer), 0) == -1) {perror("发送失败");break;}// 接收响应ssize_t num_bytes = recv(sockfd, buffer, BUFFER_SIZE, 0);if (num_bytes == -1) {perror("接收失败");break;}buffer[num_bytes] = '\0';printf("服务端响应: %s\n", buffer);}close(sockfd);return 0;
}
五、核心API详解
5.1 socket()
int socket(int domain, int type, int protocol);
| 参数 | UNIX Domain Socket专用配置 |
|---|---|
| domain | AF_UNIX(必须) |
| type | SOCK_STREAM(可靠字节流)或 SOCK_DGRAM(数据报) |
| protocol | 通常填0 |
5.2 bind()
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
- 关键点:绑定的
sun_path需有目录写权限(嵌入式系统常用/tmp或/var/run)
5.3 connect()与accept()
- 连接特性:无需三次握手,内核直接复制路径名
六、编译与测试
6.1 编译命令
# 服务端
gcc unix_server.c -o server -Wall -O2# 客户端
gcc unix_client.c -o client -Wall -O2
6.2 运行演示
# 终端1:启动服务端
$ ./server
服务端已启动,等待客户端连接...
客户端已连接: /tmp/unix_socket_example# 终端2:启动客户端
$ ./client
已连接到服务端
输入消息(输入exit退出): Hello UNIX Socket!
服务端响应: 服务端已接收 15 字节
输入消息(输入exit退出): exit
七、嵌入式场景优化建议
7.1 提升安全性
// 设置套接字文件权限(0600仅允许所有者访问)
chmod(SOCKET_PATH, S_IRUSR | S_IWUSR);
7.2 抽象命名空间
// 使用抽象套接字名(Linux特有)
serv_addr.sun_path[0] = '\0'; // 第一个字符为NULL
strncpy(serv_addr.sun_path+1, "my_abstract_socket", sizeof(serv_addr.sun_path)-2);
7.3 多客户端处理
// 使用epoll实现多路复用
struct epoll_event ev;
epoll_fd = epoll_create1(0);
ev.events = EPOLLIN;
ev.data.fd = server_fd;
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev);
八、常见问题排查
8.1 连接失败:Permission denied
# 检查套接字文件权限
ls -l /tmp/unix_socket_example
# 解决方案:
sudo chmod 777 /tmp/unix_socket_example
8.2 地址已在使用:Address already in use
# 强制删除残留套接字文件
rm -f /tmp/unix_socket_example
8.3 跨用户通信问题
- 原因:Linux权限系统限制
- 解决:设置用户组权限或使用
sudo
扩展阅读:
Linux Programmer’s Manual: unix(7) | POSIX IPC 标准 | Linux man-pages
通过本文,您可掌握UNIX Domain Socket在嵌入式Linux中的高效IPC实现方法。相比网络套接字,UDS在本地通信场景中性能更优、资源占用更少,非常适用于嵌入式设备的多模块协作!
相关文章:
嵌入式Linux网络编程:UNIX Domain Socket进程间通信(IPC)
嵌入式Linux网络编程:UNIX Domain Socket进程间通信(IPC) 【本文代码已在Linux平台验证通过】 一、UNIX Domain Socket核心优势 1.1 本地IPC方案对比 特性UNIX Domain Socket管道(Pipe)消息队列(Message Queue)共享内存(Shared Memory)跨进…...
【qt】 布局器
参考博客:https://blog.csdn.net/Fdog_/article/details/107522283 目录 布局管理器概念常见的布局管理器及特点🔵QHBoxLayout水平布局🔵QVBoxLayout垂直布局 🔵QGridLayout网格布局 🔵QFormLayout表单布局 QT 高级布…...
Hosts文件与DNS的关系:原理、应用场景与安全风险
目录 引言 Hosts文件与DNS的基本概念 2.1 什么是Hosts文件? 2.2 什么是DNS? Hosts文件与DNS的关系 Hosts文件的应用场景 4.1 本地开发与测试 4.2 屏蔽广告与恶意网站 4.3 绕过DNS污染或劫持 Hosts文件的优势 5.1 解析速度快 5.2 不受DNS缓存影…...
VMware Windows Tools 存在认证绕过漏洞(CVE-2025-22230)
漏洞概述 博通公司(Broadcom)近日修复了 VMware Windows Tools 中存在的一个高危认证绕过漏洞,该漏洞编号为 CVE-2025-22230(CVSS 评分为 9.8)。VMware Windows Tools 是一套实用程序套件,可提升运行在 VM…...
pnpm 依赖升级终极指南:从语义化版本控制到 Monorepo 全局更新的企业级实践
要使用 pnpm 更新所有依赖包,可以通过以下命令实现: 1. 更新所有依赖到符合语义化版本的范围 pnpm update该命令会根据 package.json 中定义的版本范围(如 ^1.0.0 或 ~2.3.4)更新依赖包到最新兼容版本,但不会突破版本…...
Sentinel[超详细讲解]-2
异常处理 默认情况下,Sentinel 会抛出 BlockException 异常,如果希望自定义异常,则可以使用 SentinelResource 注解的 blockHandler 属性。 1、自定义异常处理 BlockExceptionHandler 自定义异常处理类实现 BlockExceptionHandler 接口&#…...
【问题解决】Linux安装conda修改~/.bashrc配置文件后,root 用户下显示 -bash-4.2#
问题描述 在Linux安装conda下的python环境时候,修改了~/.bashrc文件,修改完成后,再次进入服务器后,登录时候显示的不是正常的[rootlocalhost ~]#,而是-bash-4.2# 原因分析: 网上原因有:/root下…...
优化webpack打包体积思路
Webpack 打包过大的问题通常会导致页面加载变慢,影响用户体验。可以从代码优化、依赖优化、构建优化等多个角度入手来减少打包体积: 代码优化 (1)按需加载(代码拆分) ① 路由懒加载 如果你的项目使用 Vu…...
RabbitMQ 技术详解:异步消息通信的核心原理与实践
这里写目录标题 RabbitMQ 技术详解:异步消息通信的核心原理与实践一、RabbitMQ 本质剖析核心架构组件 二、核心功能与应用场景主要作用典型应用场景 三、工作流程深度解析消息传递流程关键协议机制 四、Java 实现示例1. 依赖配置(Maven)2. 消…...
CF每日5题Day4(1400)
好困,感觉很累,今天想赶紧写完题早睡。睡眠不足感觉做题都慢了。 1- 1761C 构造 void solve(){int n;cin>>n;vector<vector<int>>a(n1);forr(i,1,n){//保证每个集合不同a[i].push_back(i);}forr(i,1,n){string s;cin>>s;forr(…...
LLM架构解析:NLP基础(第一部分)—— 模型、核心技术与发展历程全解析
本专栏深入探究从循环神经网络(RNN)到Transformer等自然语言处理(NLP)模型的架构,以及基于这些模型构建的应用程序。 本系列文章内容: NLP自然语言处理基础(本文)词嵌入࿰…...
k近邻算法K-Nearest Neighbors(KNN)
算法核心 KNN算法的核心思想是“近朱者赤,近墨者黑”。对于一个待分类或预测的样本点,它会查找训练集中与其距离最近的K个样本点(即“最近邻”)。然后根据这K个最近邻的标签信息来对当前样本进行分类或回归。 在分类任务中&#…...
Dubbo(21)如何配置Dubbo的注册中心?
在分布式系统中,注册中心是一个关键组件,用于服务的注册和发现。Dubbo 支持多种注册中心,包括 ZooKeeper、Nacos、Consul、Etcd 等。下面详细介绍如何配置 Dubbo 的注册中心,以 ZooKeeper 为例。 配置步骤 引入依赖:…...
【Android15 ShellTransitions】(九)结束动画+Android原生ANR问题分析
finishTransition这部分的内容不多,并且我个人的实际工作中很少接触这块,因此我之前都觉得没有必要专门开一篇去分析最后留下的这一丁点儿的动画流程。但是最近碰到了一个google原生ANR问题,正好是和这块相关的,也让我意识到了fin…...
如何让DeepSeek-R1在内网稳定运行并实现随时随地远程在线调用
前言:最近,国产AI圈里的新星——Deepseek,简直是火到不行。但是,你是不是已经对那些千篇一律的手机APP和网页版体验感到腻味了?别急,今天就带你解锁一个超炫的操作:在你的Windows电脑上本地部署…...
STM32通用定时器结构框图
STM32单片机快速入门 通用定时器框图 TIM9和TIM12 通用定时器框图 TIM9和TIM12 (二) 通用定时器框图...
How to install vmware workstation pro on Linux mint 22
概述 VMware 是一家专注于虚拟化技术和云计算解决方案的全球领先软件公司,成立于1998年,总部位于美国加州。它的核心技术是通过“虚拟化”将一台物理计算机的硬件资源(如CPU、内存、存储等)分割成多个独立的虚拟环境(…...
深度学习 Deep Learning 第11章 实用方法论
深度学习 Deep Learning 第11章 实用方法论 章节概述 本章深入探讨了机器学习在实际应用中的方法论,强调了从确定目标到逐步优化的系统性过程。在机器学习项目中,明确的目标和性能指标是指导整个开发过程的关键。通过建立初始的端到端系统,…...
【常用的中间件】
中间件(Middleware)是位于客户端和服务器之间的软件层,用于处理客户端请求和服务器响应之间的各种任务。中间件可以提供多种功能,如负载均衡、消息队列、缓存、身份验证等。以下是常用的中间件及其作用: 1. 消息队列中…...
如何排查C++程序的CPU占用过高的问题
文章目录 可能的原因程序设计的BUG系统资源问题恶意软件硬件问题 通常步骤一个简单的问题代码在windows平台上如何排查Windows Process ExplorerWinDBG 在Linux平台如何排查使用TOP GDBPerf 可能的原因 程序设计的BUG 有死循环低效算法与数据结构滥用自旋锁频繁的系统调用&a…...
个人学习编程(3-29) leetcode刷题
最后一个单词的长度: 思路:跳过末尾的空格,可以从后向前遍历 然后再利用 while(i>0 && s[i] ! ) 可以得到字符串的长度, int lengthOfLastWord(char* s) {int length 0;int i strlen(s) - 1; //从字符串末尾开始//…...
Linux云计算SRE-第二十一周
构建单节点prometheus,部署node exporter和mongo exporter。构建kibana大盘。包含主机PU使用率,主机MEM使用率,主机网络包速度。mongo db大盘,包含节点在线状态,读操作延迟等 一、实验环境准备 - 节点信息࿱…...
无人机,云台参数设置,PWM输出控制云台俯仰
目录 1、云台与飞控的连接 2、PX4飞控控制云台,QGC地面站的设置 3、遥控器映射通道设置 4、其他设置 4.1、COM_PREARM_MODE,预解锁模式 4.2、RC9_DZ ,遥控器通道死区设置 1、云台与飞控的连接 首先确定一下,设置飞控第几路…...
EtherCAT转ProfiNet协议转换网关构建西门子PLC与海克斯康机器人的冗余通信链路
一、案例背景 某电子制造企业的5G通信模块组装线,采用西门子S7-1200PLC(ProfiNet主站)进行产线调度,而精密组装工序由3台海克斯康工业机器人(EtherCAT从站)完成。由于协议差异,机器人动作与PLC…...
Android R adb remount 调用流程
目的:调查adb remount 与adb shell进去后执行remount的差异 调试方法:添加log编译adbd,替换system\apex\com.android.adbd\bin\adbd 一、调查adb remount实现 关键代码:system\core\adb\daemon\services.cpp unique_fd daemon_service_to…...
网络中常用协议
一, TCP协议 TCP(Transmission Control Protocol,传输控制协议)是互联网核心协议之一,位于传输层,为应用层提供可靠的、面向连接的数据传输服务。 1. TCP的核心特点 特性说明面向连接通信前需通过三次握手建立连接&a…...
自动驾驶04:点云预处理03
点云组帧 感知算法人员在完成点云的运动畸变补偿后,会发现一个问题:激光雷达发送的点云数据包中的点云数量其实非常少,完全无法用来进行后续感知和定位层面的处理工作。 此时,感知算法人员就需要对这些数据包进行点云组帧的处理…...
Linux内核软中断分析
一、软中断类型 在Linux内核中,中断处理分为上半部(硬中断)和下半部。上半部负责快速响应硬件事件,而下半部用于处理耗时任务,避免阻塞系统。下半部有三种机制:软中断(Softirq)、小任…...
Linux修改默认shell为zsh
一、修改模型shell为zsh 1、检查当前使用的shell echo $SHELL 2、检查当前系统支持的shell cat /etc/shells# 输出结果显示如下: """ /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/csh /bin/tcsh /usr/bin/csh /usr/bin/tcsh /usr/bin/zsh…...
k8s scheduler几种扩展方式的关系及区别
网上关于scheduler扩展介绍的文章很多,但都是东说一句西说一嘴,完全没有逻辑性,对于逻辑建构者看着很痛苦,这篇文章不会深入教你怎么扩展,而是教你几种扩展方式的关系和逻辑结构: 目前Kubernetes支持五种方…...
