DBUS socket 进程间交互原理

内容纲要

基于 ​​UNIX Domain Socket​​ 的双向通信框架,核心原理模型如下:

DBUS socket 进程间交互原理
Server[服务端] -->|监听| Socket[/tmp/dbus-name]
Client[客户端] -->|连接| Socket
Server --> Thread1[监听线程]
Client --> Thread2[方法线程]

服务端​​:创建监听套接字(socket+bind+listen),接受其他进程的连接
​​客户端​​:主动连接服务端(socket+connect),建立双向通道
​​多线程​​:使用独立线程处理连接监听(listenThread)和方法调用(methodThread)
1. 该函数实现基于 UNIX Domain Socket 的双向通信框架,主要完成:
  • ​服务端​​:创建监听套接字、绑定地址、启动监听线程
  • ​客户端​​:创建连接套接字、尝试重连、启动方法调用线程
  • ​线程安全​​:通过互斥锁 (dbus_mutex) 保护共享资源
  • UNIX Domain Socket特点​

​​ 高效性​​:内核直接传递数据,无需网络协议栈

​​ 可靠性​​:面向连接(SOCK_STREAM),保证数据顺序

​​ 安全性​​:通过文件系统权限控制访问(/tmp/dbus-*)

DBUS socket 进程间交互原理

2.程序实现

#include <sys/un.h>
#include <fcntl.h>
#include <poll.h>

#define UNIX_PATH_MAX 108
#define MAX_RETRY_ATTEMPTS 100 // 50ms * 100 = 5s
#define DETACHED_THREAD 1

/* 服务端初始化 */

static int init_server(ZRTDbusInfo dbusInfo) {
struct sockaddr_un srv_addr;
pthread_attr_t thread_attr;
// 创建UNIX域套接字
dbusInfo->socket_server = socket(AF_UNIX, SOCK_STREAM, 0);
if (dbusInfo->socket_server < 0) {
    perror("socket() server failed");
    return -1;
}

// 生成安全的套接字路径
if (snprintf(dbusInfo->unix_domain, UNIX_PATH_MAX, 
            "/tmp/dbus-%.32s", dbusInfo->name) >= UNIX_PATH_MAX) {
    fprintf(stderr, "Unix domain path too long\n");
    close(dbusInfo->socket_server);
    return -1;
}

// 清理旧套接字文件
unlink(dbusInfo->unix_domain);

// 配置地址结构
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sun_family = AF_UNIX;
strncpy(srv_addr.sun_path, dbusInfo->unix_domain, sizeof(srv_addr.sun_path)-1);
srv_addr.sun_path[sizeof(srv_addr.sun_path)-1] = '\0';

// 绑定地址
if (bind(dbusInfo->socket_server, (struct sockaddr*)&srv_addr, 
        sizeof(srv_addr)) < 0) {
    perror("bind() failed");
    close(dbusInfo->socket_server);
    return -1;
}

// 设置监听队列
if (listen(dbusInfo->socket_server, MAX_LISTEN_NUM) < 0) {
    perror("listen() failed");
    close(dbusInfo->socket_server);
    unlink(dbusInfo->unix_domain);
    return -1;
}

// 创建分离线程
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&dbusInfo->listenThread_t, &thread_attr, 
                  ZRT_Dbus_Listen_Thread, dbusInfo) != 0) {
    pthread_attr_destroy(&thread_attr);
    close(dbusInfo->socket_server);
    unlink(dbusInfo->unix_domain);
    return -1;
}
pthread_attr_destroy(&thread_attr);

return 0;

}

/* 客户端初始化(带非阻塞连接) */

static int init_client(ZRTDbusInfo dbusInfo) {
struct sockaddr_un srv_addr;
char server_path[UNIX_PATH_MAX];
pthread_attr_t thread_attr;
int flags, ret;
// 创建客户端套接字
if ((dbusInfo->socket_client = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
    perror("socket() client failed");
    return -1;
}

// 生成服务端路径
snprintf(server_path, UNIX_PATH_MAX, "/tmp/dbus-%.32s", dbusInfo->dst_name);

// 配置地址结构
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sun_family = AF_UNIX;
strncpy(srv_addr.sun_path, server_path, sizeof(srv_addr.sun_path)-1);
srv_addr.sun_path[sizeof(srv_addr.sun_path)-1] = '\0';

// 设置为非阻塞模式
flags = fcntl(dbusInfo->socket_client, F_GETFL, 0);
fcntl(dbusInfo->socket_client, F_SETFL, flags | O_NONBLOCK);

// 带超时的连接
int connected = 0;
struct pollfd pfd = { .fd = dbusInfo->socket_client, .events = POLLOUT };

for (int i = 0; i < MAX_RETRY_ATTEMPTS; ++i) {
    ret = connect(dbusInfo->socket_client, (struct sockaddr*)&srv_addr, 
                 sizeof(srv_addr));
    if (ret == 0) {
        connected = 1;
        break;
    }

    if (errno == EINPROGRESS) {
        // 使用poll等待连接完成
        if (poll(&pfd, 1, 50) > 0 && (pfd.revents & POLLOUT)) {
            socklen_t len = sizeof(ret);
            getsockopt(dbusInfo->socket_client, SOL_SOCKET, SO_ERROR, &ret, &len);
            if (ret == 0) {
                connected = 1;
                break;
            }
        }
    }
    usleep(50000); // 50ms
}

if (!connected) {
    fprintf(stderr, "Connection timeout to %s\n", dbusInfo->dst_name);
    close(dbusInfo->socket_client);
    dbusInfo->socket_client = -1;
    return -1;
}

// 恢复阻塞模式
fcntl(dbusInfo->socket_client, F_SETFL, flags);

// 创建方法线程
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&dbusInfo->methodThread_t, &thread_attr, 
                  ZRT_Dbus_Method_Thread, dbusInfo) != 0) {
    pthread_attr_destroy(&thread_attr);
    close(dbusInfo->socket_client);
    dbusInfo->socket_client = -1;
    return -1;
}
pthread_attr_destroy(&thread_attr);

return 0;
}

/* 主注册函数 */

int ZRT_Dbus_Register(ZRTDbusInfo *dbusInfo) {
// 参数校验
if (!dbusInfo || !dbusInfo->name[0]) {
fprintf(stderr, "Invalid parameters\n");
return -1;
}
// 初始化互斥锁
if (pthread_mutex_init(&dbusInfo->dbus_mutex, NULL) != 0) {
    perror("pthread_mutex_init failed");
    return -1;
}

// 服务端初始化
if (dbusInfo->interface_num > 0) {
    if (init_server(dbusInfo) < 0) {
        goto cleanup_mutex;
    }
}

// 客户端初始化
if (dbusInfo->dst_name[0]) {
    if (init_client(dbusInfo) < 0) {
        goto cleanup_server;
    }
}

return 0;

cleanup_server:
if (dbusInfo->socket_server >= 0) {
  close(dbusInfo->socket_server);
  unlink(dbusInfo->unix_domain);
}
cleanup_mutex:
  pthread_mutex_destroy(&dbusInfo->dbus_mutex);
  return -1;
}

3。 dbus 通信优势

目标实现方式优势
​双向通信​同时支持服务端和客户端模式可同时处理请求和主动发起调用
​资源安全​互斥锁保护 + 错误路径资源释放避免内存/文件描述符泄漏
​连接可靠性​客户端带超时重连机制容忍服务端暂时不可用
​高并发处理​分离监听线程和方法线程避免主线程阻塞
版权声明

版权声明

内容来源及使用限制

欢迎访问 TomgZHE研习社(网址:https://blog.tomgzhe.com)。本网站部分文章内容源自网络,仅作学习交流与参考分享;若您发现有内容涉嫌侵权,请立即联系 tomgzhe@qq.com,我们将在接到通知后的 48 小时内核实并删除相关侵权内容。

软件资源相关规定

本网站为个人非盈利性质的站点,所有软件资源均来自网络。这些资源仅用于个人学习、研究和参考,严禁用于任何商业用途。您下载和使用本网站软件资源即表示您同意仅将其用于学习目的,若因违反此规定导致任何法律纠纷或损失,责任由您自行承担。

原创版权

本网站上的原创内容,包括但不限于文字作品、自行设计的图片、独家制作的音频视频等,其版权均归本网站所有。未经本网站书面授权,任何组织或个人不得擅自复制、转载、摘编、传播或以其他任何方式使用这些原创内容。如需使用,请提前与我们联系并获得书面许可,同时需在显著位置注明出处及作者信息。

转载与引用规范

若您需转载本网站文章,务必注明文章来源为 “[],原文链接:[]”;对于有明确作者署名的文章,还需完整保留作者姓名。在引用本网站内容时,请确保内容准确无误,并遵循学术及行业的引用规范。

Like (0)
Donate 微信扫一扫打赏 微信扫一扫打赏 支付宝扫一扫打赏 支付宝扫一扫打赏
tomgzhe的头像tomgzhe
Previous 2025年2月25日 16:58
Next 2025年9月11日

相关推荐

发表回复

Please Login to Comment

Comments(1)

  • […]        系统以顶层的​​APP应用模块​​为入口,通过​​Dbus-A​​和​​network Dbus(Dbus-B)​​双接口与中间件通信:Dbus-A负责接收上层应用的广播、信号与方法调用,Dbus-B则专用于网络方法请求。核心中间层由​​lib SDK​​实现业务逻辑整合,其向下提供网络服务API(如OTA更新、netlink通信、设备上电控制等),并基于共享内存机制将数据流拆分为​​双独立通道​​——左侧通道通过“channel ctrl”模块管理SDIO接口的WiFi驱动,实现网络数据流传输;右侧通道通过“media ctrl”模块控制MIPI-CSI接口的摄像头驱动,处理图像媒体流。        两通道在共享内存层实现硬件访问隔离,最终由底层驱动直接操作SDIO与MIPI-CSI硬件协议完成数据交互。整个架构通过Dbus接口解耦应用与硬件逻辑,利用并行通道设计兼顾网络与媒体数据的高效处理,形成层次分明、扩展灵活的系统解决方案。 对DBUG不熟悉,可看文章DBUS交互实现。 […]

联系我们

联系我们

400-800-6666

在线咨询: QQ交谈 邮件:tomgzhe@qq.com 工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
关注微信
SHARE
TOP
蛇年新气象!从2025年2月起,本博客将在保留科技板块基础上,新增生活美学、个人成长等多元内容,希望能为大家带来更丰富的阅读体验,敬请期待!