日韩性视频-久久久蜜桃-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)的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 国产69精品麻豆 | 嫩草视屏| 久久免费福利视频 | 麻豆精品a∨在线观看 | 三上悠亚在线一区 | 国产美女无遮挡免费视频 | 午夜视频久久 | 一区二区三区在线视频免费观看 | 日韩蜜桃视频 | 国产18禁黄网站免费观看 | 天堂在线www | 毛片久久久久 | 一本一道久久a久久综合蜜桃 | 欧美日韩你懂的 | 日本熟妇人妻中出 | 92久久| 久久久成人精品 | 欧美大喷水吹潮合集在线观看 | 青青草国产成人99久久 | 国产自产自拍 | 中国精品一区二区 | 淫片在线 | 日本欧美色图 | 亚洲性自拍 | 日本一区二区在线 | 国产丝袜美腿一区二区三区 | 日韩黄色网络 | 美日韩精品一区二区 | 超碰在线亚洲 | 日本美女动态 | 98成人网 | 色哟哟一区二区三区 | 亚洲精品免费电影 | 国产a国产 | 色射网 | 黄色网页在线免费观看 | 国产一区二区三区日韩 | 韩国性猛交╳xxx乱大交 | 在线免费观看麻豆 | 日本无遮挡边做边爱边摸 | 日本美女三级 | 久久久久久91亚洲精品中文字幕 | 在线观看免费视频a | 亚洲欧美制服丝袜 | 丁香婷婷久久久综合精品国产 | 夜夜操夜夜摸 | 国产天天骚| 亚洲日本va中文字幕 | 夜夜操影视 | 好吊视频一区二区三区四区 | 亚洲欧美乱综合图片区小说区 | 亚洲一区二区三区综合 | 一区二区三区在线观看 | 亚洲色图偷拍 | 91在线看片 | 一卡二卡在线观看 | 国产一区二区影院 | 国产日韩欧美另类 | 亚洲福利精品 | 日韩草逼| 欧美18aaaⅹxx | 免费观看成人在线视频 | 色老久久 | 少妇光屁股影院 | 亚洲高清网 | www.97色 | 精品无码人妻一区二区三区 | xxxxx黄色片 噜噜噜噜噜色 | 麻豆午夜 | 欧美一区免费观看 | 中文字幕视频一区 | 秋霞无码一区二区 | 精品免费国产 | av影院在线观看 | 国产鲁鲁视频在线观看免费 | 国产清纯在线 | zjzjzjzjzj亚洲女人 | www国产精品内射老熟女 | 欧美精品区 | 手机在线小视频 | 欧美精品一级片 | 国产精品一区二区无线 | 中国少妇毛片 | 黄色一级片免费 | 精品一区二区三区在线观看视频 | 操比网站 | 亚洲欧美国产精品久久久久久久 | 综合久久网 | 区一区二视频 | 三级精品在线观看 | 国产无套精品一区二区三区 | 精品国产丝袜一区二区三区乱码 | 成人在线免费视频观看 | 欧美日韩在线一区二区三区 | av免费观| 日韩欧美中文字幕一区二区三区 | 欧洲色综合 | 免费无遮挡在线观看视频网站 | 国产婷婷一区二区 |