日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于DBus的进程间通信(IPC)

發布時間:2025/3/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于DBus的进程间通信(IPC) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原文地址:http://sy198704.is-programmer.com/posts/33060.html

最近在研究進程間通信,linux下進程間通信的方式主要有Pipe(管道),FIFO(命名管道),信號,共享內存,消息隊列,信號燈等,這些方式各有各得特點,如管道是linux下命令行中常用的,用于父子進程的通信。但是這些通信方式都比較原始,要屬功能最強大的IPC應該是dbus,故查看了一下dbus的資料,但是資料相對較少,特別是有關python的部分。?

1.dbus概念

網上有一篇叫“D-Bus?Tutorial”的文章,流傳較廣。

D-Bus是針對桌面環境優化的IPC(interprocess?communication?)機制,用于進程間的通信或進程與內核的通信。最基本的D-Bus協議是一對一的通信協議。但在很多情況下,通信的一方是消息總線。消息總線是一個特殊的應用,它同時與多個應用通信,并在應用之間傳遞消息。下面我們會在實例中觀察消息總線的作用。消息總線的角色有點類似與X系統中的窗口管理器,窗口管理器既是X客戶,又負責管理窗口。

支持dbus的系統都有兩個標準的消息總線:系統總線和會話總線。系統總線用于系統與應用的通信。會話總線用于應用之間的通信。網上有一個叫d-feet的python程序,我們可以用它來觀察系統中的dbus世界。

圖1、由d-feet觀察到的D-Bus世界

dbus還提供了兩個命令行工具用于dbus測試,dbus-send和dbus-monitor,前一個命令用于測試信號的發送,后一個命令用于監控dbus的數據流。

2.dbus概念

有關dbus的基礎知識不在本文的范圍內,具體的參見dbus的文檔。下面給出dbus常用的流程。

2.1建立服務的流程

dbus_bus_get(),建立一個dbus連接;

dbus_bus_request_name(),為這個dbus連接(DbusConnection)起名,這個名字將會成為我們在后續進行遠程調用的時候的服務名;

然后我們進入監聽循環?--?dbus_connection_read_write();

從總線上取出消息?--?dbus_connection_pop_message();

并通過比對消息中的方法接口名和方法名?--?dbus_message_is_method_call();

如果一致,那么我們跳轉到相應的處理中去;

在相應的處理中,我們會從消息中取出遠程調用的參數。并且建立起回傳結果的通路?--?reply_to_method_call()。回傳動作本身等同于一次不需要等待結果的遠程調用。

2.2建立服務的流程

建立好dbus連接之后,為這dbus連接命名,申請一個遠程調用通道?--?dbus_message_new_method_call(),注意,在申請遠程調用通道的時候,需要填寫服務器名,本次調用的接口名,和本次調用名(方法名)。壓入本次調用的參數?--?dbus_message_iter_init_append();?dbus_message_iter_append_basic(),實際上是申請了一個首地址,我們就是把我們真正要傳的參數,往這個首地址里面送(送完之后一般都會判斷是否內存越界了)。然后就是啟動發送調用并釋放發送相關的消息結構?--?dbus_connection_send_with_reply()。這個啟動函數中帶有一個句柄。我們馬上會阻塞等待這個句柄給我們帶回總線上回傳的消息。當這個句柄回傳消息之后,我們從消息結構中分離出參數。用dbus提供的函數提取參數的類型和參數?--?dbus_message_iter_init();?dbus_message_iter_next();?dbus_message_iter_get_arg_type();?dbus_message_iter_get_basic()。也就達成了我們進行本次遠程調用的目的了。

2.3發送信號的流程

建立一個dbus連接之后,為這個dbus連接起名,建立一個發送信號的通道,注意,在建立通道的函數中,需要我們填寫該信號的接口名和信號名?--?dbus_message_new_signal()。然后我們把信號對應的相關參數壓進去?--?dbus_message_iter_init_append();?dbus_message_iter_append_basic()。然后就可以啟動發送了?--?dbus_connection_send();?dbus_connection_flush。

2.4信號接收流程

建立一個dbus連接之后,為這個dbus連接起名,為我們將要進行的消息循環添加匹配條件(就是通過信號名和信號接口名來進行匹配控制的)?--?dbus_bus_add_match()。我們進入等待循環后,只需要對信號名,信號接口名進行判斷就可以分別處理各種信號了。在各個處理分支上。我們可以分離出消息中的參數。對參數類型進行判斷和其他的處理。

3.?一個C語言的示例代碼

網上大部分代碼都是基于dbus的一個封裝庫libdbus做的,以及使用glib,gtk的事件循環;為了減少庫的依賴,直接使用C語言調用dbus的底層函數編寫一個遠程調用的示例代碼,代碼很簡單,沒使用GObject等一些復雜的庫。

遠程調用的服務器代碼,用于監控,代碼如下:

?
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166#include?<dbus/dbus.h>#include?<stdbool.h>#include?<unistd.h>#include?<stdio.h>#include?<stdlib.h>voidreply_to_method_call(DBusMessage*?msg,?DBusConnection*?conn){DBusMessage*?reply;DBusMessageIter?args;boolstat?=?true;dbus_uint32_t?level?=?21614;dbus_uint32_t?serial?=?0;char*?param?=?"";//?read?the?argumentsif(!dbus_message_iter_init(msg,?&args))fprintf(stderr,?"Message?has?no?arguments!\n");?elseif(DBUS_TYPE_STRING?!=?dbus_message_iter_get_arg_type(&args))?fprintf(stderr,?"Argument?is?not?string!\n");?elsedbus_message_iter_get_basic(&args,??m);printf("Method?called?with?%s\n",?param);//?create?a?reply?from?the?messagereply?=?dbus_message_new_method_return(msg);//?add?the?arguments?to?the?replydbus_message_iter_init_append(reply,?&args);if(!dbus_message_iter_append_basic(&args,?DBUS_TYPE_BOOLEAN,?&stat))?{?fprintf(stderr,?"Out?Of?Memory!\n");?exit(1);}if(!dbus_message_iter_append_basic(&args,?DBUS_TYPE_UINT32,?&level))?{?fprintf(stderr,?"Out?Of?Memory!\n");?exit(1);}//?send?the?reply?&&?flush?the?connectionif(!dbus_connection_send(conn,?reply,?&serial))?{fprintf(stderr,?"Out?Of?Memory!\n");?exit(1);}dbus_connection_flush(conn);//?free?the?replydbus_message_unref(reply);}staticvoidreply_to_Introspect(DBusMessage*?msg,?DBusConnection*?conn){/*反饋的消息*/char*xml?=?"<!DOCTYPE?node?PUBLIC?\"-//freedesktop//DTD?D-BUS?Object?Introspection?1.0//EN\"\n\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n""<node>\n""?<interface?name=\"org.freedesktop.DBus.Introspectable\">\n""?<method?name=\"Introspect\">\n""?<arg?name=\"introspection_xml\"?direction=\"out\"?type=\"s\"/>\n""?</method>\n?</interface>\n""?<interface?name=\"test.method.Type\">\n""?<method?name=\"Method\">\n""?<arg?name=\"level\"?direction=\"out\"?type=\"i\"/>\n""?<arg?name=\"serial\"?direction=\"out\"?type=\"i\"/>\n""?</method>\n""?</interface>\n""</node>\n";DBusMessage*?reply;DBusMessageIter?args;boolstat?=?true;//?create?a?reply?from?the?messagereply?=?dbus_message_new_method_return(msg);//?add?the?arguments?to?the?replydbus_message_iter_init_append(reply,?&args);if(!dbus_message_iter_append_basic(&args,?DBUS_TYPE_STRING,?&xml))?{?printf("Dbus?Error:?append?args?error\n");dbus_message_unref(reply);return;}//?send?the?reply?&&?flush?the?connectionif(!dbus_connection_send(conn,?reply,?NULL))?{printf("Dbus?Error:?send?error\n");dbus_message_unref(reply);return;}dbus_connection_flush(conn);//?free?the?replydbus_message_unref(reply);}/***?Server?that?exposes?a?method?call?and?waits?for?it?to?be?called*/voidlisten()?{DBusMessage*?msg;DBusMessage*?reply;DBusMessageIter?args;DBusConnection*?conn;DBusError?err;intret;char*?param;printf("Listening?for?method?calls\n");//?initialise?the?errordbus_error_init(&err);//?connect?to?the?bus?and?check?for?errorsconn?=?dbus_bus_get(DBUS_BUS_SESSION,?&err);if(dbus_error_is_set(&err))?{?fprintf(stderr,?"Connection?Error?(%s)\n",?err.message);?dbus_error_free(&err);?}if(NULL?==?conn)?{fprintf(stderr,?"Connection?Null\n");?exit(1);?}//?request?our?name?on?the?bus?and?check?for?errorsret?=?dbus_bus_request_name(conn,?"test.method.server",?DBUS_NAME_FLAG_REPLACE_EXISTING?,?&err);if(dbus_error_is_set(&err))?{?fprintf(stderr,?"Name?Error?(%s)\n",?err.message);?dbus_error_free(&err);}if(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER?!=?ret)?{?fprintf(stderr,?"Not?Primary?Owner?(%d)\n",?ret);exit(1);?}//?loop,?testing?for?new?messageswhile(true)?{//?non?blocking?read?of?the?next?available?messagedbus_connection_read_write(conn,?0);msg?=?dbus_connection_pop_message(conn);//?loop?again?if?we?haven't?got?a?messageif(NULL?==?msg)?{?sleep(1);?continue;?}//?check?this?is?a?method?call?for?the?right?interface?&?methodif(dbus_message_is_method_call(msg,?"test.method.Type",?"Method"))?reply_to_method_call(msg,?conn);/*實現反射接口*/if(dbus_message_is_method_call(msg,?"org.freedesktop.DBus.Introspectable",?"Introspect"))?reply_to_Introspect(msg,?conn);//?free?the?messagedbus_message_unref(msg);}}intmain(intargc,?char**?argv){listen();return0;}?

代碼中很關鍵的一個地方是一個標準接口的實現,該接口雖說無實際意義,僅僅是反射出該session的接口信息,包含各個接口信息和信號信息,但是該信息在python版的dbus中調用很重要,否則python的調用會失敗。

編譯命令如下

?
1gcc?-o?main?main.c?`pkg-config?--cflags?--libs?dbus-1`

可以用d-feet測試一下:

用dbus-send測試命令如下:

?
1dbus-send?--session?--type=method_call?--print-reply?--dest=test.method.server?/?test.method.Type.Method

客戶端代碼(及遠程調用的代碼):

?
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119#include?<dbus/dbus.h>#include?<stdbool.h>#include?<unistd.h>#include?<stdio.h>#include?<stdlib.h>/**?*?Call?a?method?on?a?remote?object?*/voidquery(char*?param)?{?DBusMessage*?msg;?DBusMessageIter?args;?DBusConnection*?conn;?DBusError?err;?DBusPendingCall*?pending;?intret;?boolstat;?dbus_uint32_t?level;?printf("Calling?remote?method?with?%s\n",?param);?//?initialiset?the?errors?dbus_error_init(&err);?//?connect?to?the?system?bus?and?check?for?errors?conn?=?dbus_bus_get(DBUS_BUS_SESSION,?&err);?if(dbus_error_is_set(&err))?{?fprintf(stderr,?"Connection?Error?(%s)\n",?err.message);?dbus_error_free(&err);?}?if(NULL?==?conn)?{?exit(1);?}?//?request?our?name?on?the?bus?ret?=?dbus_bus_request_name(conn,?"test.method.caller",?DBUS_NAME_FLAG_REPLACE_EXISTING?,?&err);?if(dbus_error_is_set(&err))?{?fprintf(stderr,?"Name?Error?(%s)\n",?err.message);?dbus_error_free(&err);?}?if(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER?!=?ret)?{?exit(1);?}?//?create?a?new?method?call?and?check?for?errors?msg?=?dbus_message_new_method_call("test.method.server",?//?target?for?the?method?call?"/test/method/Object",?//?object?to?call?on?"test.method.Type",?//?interface?to?call?on?"Method");?//?method?name?if(NULL?==?msg)?{?fprintf(stderr,?"Message?Null\n");?exit(1);?}?//?append?arguments?dbus_message_iter_init_append(msg,?&args);?if(!dbus_message_iter_append_basic(&args,?DBUS_TYPE_STRING,??m))?{?fprintf(stderr,?"Out?Of?Memory!\n");?exit(1);?}?//?send?message?and?get?a?handle?for?a?reply?if(!dbus_connection_send_with_reply?(conn,?msg,?&pending,?-1))?{?//?-1?is?default?timeout?fprintf(stderr,?"Out?Of?Memory!\n");?exit(1);?}?if(NULL?==?pending)?{?fprintf(stderr,?"Pending?Call?Null\n");?exit(1);?}?dbus_connection_flush(conn);?printf("Request?Sent\n");?//?free?message?dbus_message_unref(msg);?//?block?until?we?recieve?a?reply?dbus_pending_call_block(pending);?//?get?the?reply?message?msg?=?dbus_pending_call_steal_reply(pending);?if(NULL?==?msg)?{?fprintf(stderr,?"Reply?Null\n");?exit(1);?}?//?free?the?pending?message?handle?dbus_pending_call_unref(pending);?//?read?the?parameters?if(!dbus_message_iter_init(msg,?&args))?fprintf(stderr,?"Message?has?no?arguments!\n");?elseif(DBUS_TYPE_BOOLEAN?!=?dbus_message_iter_get_arg_type(&args))?fprintf(stderr,?"Argument?is?not?boolean!\n");?elsedbus_message_iter_get_basic(&args,?&stat);?if(!dbus_message_iter_next(&args))?fprintf(stderr,?"Message?has?too?few?arguments!\n");?elseif(DBUS_TYPE_UINT32?!=?dbus_message_iter_get_arg_type(&args))?fprintf(stderr,?"Argument?is?not?int!\n");?elsedbus_message_iter_get_basic(&args,?&level);?printf("Got?Reply:?%d,?%d\n",?stat,?level);?//?free?reply?dbus_message_unref(msg);?}?intmain(intargc,?char**?argv){char*?param?=?"no?param";?query(param);return0;}?

執行結果:

Calling?remote?method?with?no?param
Request?Sent
Got?Reply:?1,?21614

4.Pthon調用dbus

?
123456789#!/usr/bin/env?python#?-*-?coding:utf-8?-*-importdbusbus?=dbus.SessionBus()bus_obj?=bus.get_object('test.method.server',?'/')interface?=dbus.Interface(bus_obj,?'test.method.Type')info?=interface.Method()printinfo

?

?

轉載于:https://blog.51cto.com/qsjming/1208070

總結

以上是生活随笔為你收集整理的基于DBus的进程间通信(IPC)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线免费av观看 | 亚洲成人一区二区三区 | 四虎影库在线播放 | 国产三级一区二区三区 | 九一精品一区 | 操视频网站 | 欧美日韩国产免费 | 亚洲国产日韩在线一区 | 欧美色图12p | 日本少妇色视频 | 国产精品资源在线观看 | 99精品视频一区二区 | 国产精品ⅴa有声小说 | 91成人黄色| 露脸啪啪清纯大学生美女 | 婷婷色亚洲 | 男人天堂国产 | 日韩免| 最新中文字幕2019 | 国产11页 | 浮力影院国产第一页 | 欧美日韩在线综合 | 黑人中文字幕一区二区三区 | 91一区二区三区在线 | 国产亚洲综合在线 | 午夜激情av在线 | 凹凸国产熟女精品视频 | 日本少妇bbwbbw精品 | 自拍1页| 欧美日韩激情在线观看 | av不卡在线看 | 97精品一区 | 福利在线一区二区三区 | 欧美一区三区二区在线观看 | 阿v天堂2017 欧美小视频在线观看 | 亚洲精品美女在线观看 | 日韩成人一区二区视频 | a一级免费视频 | 碰碰97| 69国产在线 | 警察高h荡肉呻吟男男 | 在线日韩一区二区 | 先锋影音一区二区三区 | 国产精品一区二区人妻喷水 | juliaann办公室丝袜大战 | 校园春色自拍偷拍 | 污视频网站在线看 | 在线视频观看你懂得 | 网友自拍第一页 | 日本女人一级片 | 国精品一区 | 亚洲精品国产电影 | 国产黄大片在线观看画质优化 | 人人九九精 | 久久av资源 | 久久97 | 黄色小电影网址 | 日韩在线视频在线观看 | 麻豆回家视频区一区二 | 亚洲天堂一区在线 | 国产视频网 | 韩国黄色网 | 国产精品综合视频 | 中文字幕精品国产 | 天堂网av手机版 | 欧美人与禽zozzozzo | 伊人春色在线 | 亚洲美免无码中文字幕在线 | 天天综合网久久 | 国产冒白浆 | 亚洲无码精品一区二区三区 | 免费成人福利视频 | 欧美日韩视频无码一区二区三 | 亚洲视频福利 | 福利在线免费 | 色爽 av| 日本激情网 | 欧色图 | 日韩免费黄色片 | 性一交一乱一伧老太 | 欧美a一级 | 最近中文字幕在线观看视频 | 亚洲精品国产av | 一区二区不卡视频在线观看 | 欧美精品久久久久a | 婷婷久久伊人 | 中文字幕在线视频第一页 | 久久精品高清 | 国产精品久久久久久人妻精品动漫 | 91玉足脚交白嫩脚丫 | 国产夫妻精品 | 加勒比日韩 | 免费中文字幕日韩 | 精品自拍视频在线观看 | 久久精品国产精品 | 亚洲熟妇无码一区二区三区导航 | 亚洲一区二区三区在线 | 亚洲五月花 | 一级黄色大片免费观看 |