What is IPC

IPC [Inter-Process Communication] 进程间通信,指至少两个进程或线程间传送数据或信号的一些技术或方法。在Linux/Unix中,提供了许多IPC。Unix七大IPC:

  • Pipe:无名管道,最基本的IPC,单向通信,仅在父/子进程之间,也就是将一个程序的输出直接交给另一个程序的输入。常见使用为 ps -ef|grep xxx
  • FIFO [(First in, First out)] 或 有名管道(named pipe:与Pipe不同,FIFO可以让两个不相关的进程可以使用FIFO。单向。
  • Socket 和 Unix Domain Socket:socket和Unix套接字,双向。适用于网络通信,但也可以在本地使用。适用于不同的协议。
  • 消息队列 Message Queue: SysV 消息队列、POSIX 消息队列。
  • Signal: 信号,是发送到正在运行的进程通知以触发其事件的特定行为,是IPC的一种有限形式。
  • Semaphore:信号量,通常用于IPC或同一进程内的线程间通信。他们之间使用队列进行消息传递、控制或内容的传递。(常见SysV 信号量、POSIX 信号量)
  • Shared memory:(常见SysV 共享内存、POSIX 共享内存)。共享内存,是在进程(程序)之间传递数据的有效方式,目的是在其之间提供通信。

每种IPC都有不通的特点,每种方式对资源的使用及性能都是不通的

  • 管道 I/O是最快的,但为单向通信,需要工作在 父/子 进程关系之间。
  • UNIX 套接字可以在本地连接不同的进程,并且具有更高的带宽,并且没有固有的消息边界。
  • TCP/IP套接字可以连接任何进程。并且可以通过网络连接,但是对资源会有更多的开销,同样的没有固定的消息边界。

Reference

comparsion Unix/Linux IPC

What is D-Bus

提到,D-Bus就不能不提一下freedesktop,而 D-Bus 仅仅作为freedesktop.org的一部分。

D-Bus 桌面总线 (Desktop Bus),的简写,也是Linux- IPC机制,不同于Unix 7大基础IPC的是,D-Bus是在这些IPC类型之上实现的中间件IPC,D-Bus使用了基础IPC中一种过多种,其设计的目的是在Linux桌面环境,提供服务的标准化。但目前并没有合入主线内核中。

作为中间件IPC,D-Bus的性能较低与其他IPC模式,因为在通信过程中会进行很多上下文切换,如果通过Dbus来发送消息,会先将其发送到内核,然后将其送回D-Bus。AF_BUS 补丁是新的套接字类型,用来减少D-Bus上下文的切换。

更多可参考:https://en.wikipedia.org/wiki/D-Bus

D-Bus组成

D-Bus是 一个IPC的实现方式,在架构上分位三层。

  • Layer 1 libdbus:freedesktop机构提供的一个免费开源的一个由C语言编写的 low-level API 。是提供dbus功能的库。是高级API绑定的低级API。
  • Layer 2 dbus daemon:dbus实现的IPC守护进行,随Linux启动,通过不通进程对其的连接,实现了多进程间消息的路由(包含内核、网络、桌面等)
  • Layer 3 Wapper libraries (high-level API):low-level API libdbus的封装 ,例如 libdbus-qt libdbus-python github.com/godbus/dbus,这些不同编程语言实现的Wapper是不同开发者应该使用的lib,其简化了D-Bus的开发难度。

Reference

dbus-tutorial

dbus 基本概念

总线

在 D-Bus 中,bus是一个核心概念。它是应用程序可以进行方法调用、发送信号和侦听信号的通道。有两种预定义的bus:会话总线系统总线

  • 会话总线(Session Bus):普通进程创建,可同时存在多条。会话总线属于某个进程私有,它用于进程间传递消息。

  • 系统总线(System Bus):在引导时就会启动,它由操作系统和后台进程使用,安全性非常好,以使得任意的应用程序不能欺骗系统事件。当然,如果一个应用程序需要接受来自系统总线的消息,他也可以直接连接到系统总线中,但是他能发送的消息是受限的。系统总线最常见的用途是在系统范围事件发生时发送系统范围的通知。添加新的存储设备、网络连接更改事件和关闭相关事件都是系统总线何时更适合通信总线的示例。

通常情况下只存在一个System Bus,但可以存在多个Session Bus(每个桌面会话一个)。

总线以dbus-daemon的形式存在与系统中,该进程专门将消息从一个进程传递到另一个进程。该守护进程还将向总线上的所有应用程序转发通知。

bus name

总线名称 Bus Name,不能单单以字面意思 总线名称 来理解,官方对其解释为:Connections have one or more bus names associated with them. A connection has exactly one bus name that is a unique connection name.,可以出bus name其实是用来连接名称。主要是用来标识一个应用和消息总线的连接。总线名称主要分为两类:唯一名称与公共名称。

  • 唯一连接名称 unique connection names :以冒号(':')字符开头的 bus name是唯一的连接名称。例如 :1.0。每个连接都有一个唯一名。在一个 消息总线的生命期内,不会有两个连接有相同的唯一名。
  • 公共连接名称 well-known bus names:公共名称是以反向DNS域名(小写)例如:org.fedoraproject.FirewallD1
    • 如果DNS 域名包含连字符/减号,则应将其替换为下划线,如果包含数字,则应通过添加下划线进行转义。例如: 7-zip.org的bus name应该定义为 org._7_zip.Archiver

Reference

bus name

对象路径

对象路径(Object Paths) 是用于引用对象实例的名称(类似于 C++ 或 Java 对象)。从概念上来说,D-Bus在消息交换中每个参与者都有任意个对象实例,如文件系统一样,Dbus中的参与者中的对象实例也会形成一个层次树。如,在CentOS7中 firewalld开发的D-Bus API 使用了/org/fedoraproject/FirewallD1的层次结构。

在定义一个对象路径时,需要注意以下:

  • 路径可以是任意长度
  • 路径必须以 ASCII '/'(整数 47)字符开头,并且必须由以斜杠字符分隔的元素组成。
  • 每个元素只能包含 ASCII 字符 [AZ][az][0-9]_
  • 不允许出现 空字符串
  • 多个 / 字符不能依次出现。 除非路径是根路径(单个/字符),否则不允许尾随 /字符。

接口名称

interface,在每个 Object Path都包含多个接口,一般情况下接口名称应以反向 DNS 域名开头(小写),(同 Java 中的接口名称)。在命名规则上,与bus name相同。

例如:CentOS7中 firewalld开发的D-Bus API 定义的管理zone的接口 org.fedoraproject.FirewallD1.config.zone。如果DNS名称中包含-,则应将其替换为下划线 _。如果DNS 域名包含紧跟在 . 之后的数字,则接口名称应在数字之前添加一个下划线。例如,如果 7-zip.org 插件定义了一个接口,应该被命名为org._7_zip.Plugin.

成员方法名称

成员方法名称,Member names ,对于定义了接口后,需要实现其接口的放法,如需要获得firewalld的zone时,就可以调用 org.fedoraproject.FirewallD1.getDefaultZone 。在D-Bus中Member names通常由“驼峰式”(camel-case)命名 。

dbus

在Linux中,如CentOS dbus包括 dbus daemon及一些cli commad。这些包

dbuslib

D-Bus的消息

最基本的D-Bus协议是一对一的通信协议。与直接使用socket不同,D-Bus是面向消息的协议。 D-Bus的所有功能都是通过在连接上流动的消息完成的。

而在D-Bus中有四种类型的消息

  • METHOD_CALL 方法调用
  • METHOD_RETURN 方法返回
  • ERROR 错误
  • SIGNAL 信号:与方法调用不同,信号发射没有响应。信号发射只是一个类型为 SIGNAL 的消息。它必须具有三个标头字段:PATH给出发出信号的对象,加上INTERFACEMEMBER给出信号的完全限定名称。

消息返回的类型

Conventional name 十进制值 说明
INVALID 0 这是个无效类型
METHOD_CALL 1 方法调用,该方法会有提示
METHOD_RETURN 2 方法返回的数据
ERROR 3 错误返回,第一个是其错误的信息
SIGNAL 4 信号的发射

CentOS的dbus服务管理

在CentOS7中,作为systemd的一部分D-BUS会从Systemd获取套接字文件描述符,并使用D-Bus交换当前进程生成的socket信息。而PID 1 不使用 PolicyKit 来控制对特权操作的访问,而是完全依赖于 low-level API D-Bus 。(这样做是为了避免 PolicyKit 和 systemd/PID 1 之间的循环依赖。)而有些特权进程(例如关机/重启/挂起/登陆)可以通过logind进行管理的。

由此,可以知道在CentOS中,dbus相关的服务大概有 dbus,与 logind

dbus包含:

  • dbus-daemon:dbus架构中 layer 2的 dbus-damon

  • dbus-send: dbus提供的命令行工具,可以用dbus-send来发送消息。

  • dbus-monitor: dbus提供的命令行工具,用于监视总线上流动的消息。

  • dbus-launch: shell脚本启动消息总线的命令行工具

dbus配置文件说明

dbus-daemon守护进程,有两个配置文件,一个为 session bus,另外一个为 system bus。

标准的system bus文件 /usr/local/share/dbus-1/system.conf session bus配置 /usr/local/share/dbus-1/session.conf中配置。在一般情况下,不会操作这两个文件,因其会引入 /etc/dbus-1 中的system.confsession.conf

配置文件包含的标签:

更多的注释可以参考:dbus-daemon

# 根元素
<busconfig> <!-- 根据指定的 -system或 -session 来选择的配置文件 -->
<type>system</type> <!-- dbus-daemon运行的用户 -->
<user>dbus</user> <!-- Fork into daemon mode -->
<fork/> <!-- We use system service launching using a helper -->
<standard_system_servicedirs/> <!-- This is a setuid helper that is used to launch system services -->
<servicehelper>//usr/libexec/dbus-1/dbus-daemon-launch-helper</servicehelper> <!-- Write a pid file -->
<pidfile>/run/dbus/messagebus.pid</pidfile> <!-- Enable logging to syslog -->
<syslog/> <!-- 指定授权机制。如果不存在,所有的机制都被允许。 -->
<auth>EXTERNAL</auth> <!-- 总线监听的地址,支持unix socket,tcp,system等
-->
<listen>unix:path=/run/dbus/system_bus_socket</listen>
<listen>unix:path=/tmp/foo</listen>
<listen>tcp:host=localhost,port=1234</listen> <policy context="default">
<!-- All users can connect to system bus -->
<allow user="*"/> <!-- Holes must be punched in service configuration files for
name ownership and sending method calls -->
<deny own="*"/>
<deny send_type="method_call"/> <!-- Signals and reply messages (method returns, errors) are allowed
by efault -->
<allow send_type="signal"/>
<allow send_requested_reply="true" send_type="method_return"/>
<allow send_requested_reply="true" send_type="error"/> <!-- All messages may be received by default -->
<allow receive_type="method_call"/>
<allow receive_type="method_return"/>
<allow receive_type="error"/>
<allow receive_type="signal"/> <!-- Allow anyone to talk to the message bus -->
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus" />
<allow send_destination="org.fedoraproject.FirewallD1"
send_interface="org.fedorapproject.FirewallD1" />
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus.Introspectable"/>
<!-- But disallow some specific bus services -->
<deny send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus"
send_member="UpdateActivationEnvironment"/>
<deny send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus.Debug.Stats"/>
<deny send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.systemd1.Activator"/>
</policy> <!-- Only systemd, which runs as root, may report activation failures. -->
<policy user="root">
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.systemd1.Activator"/>
</policy> <!-- root may monitor the system bus. -->
<policy user="root">
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus.Monitoring"/>
</policy> <!-- If the Stats interface was enabled at compile-time, root may use it.
Copy this into system.local.conf or system.d/*.conf if you want to
enable other privileged users to view statistics and debug info -->
<policy user="root">
<allow send_destination="org.freedesktop.DBus"
send_interface="org.freedesktop.DBus.Debug.Stats"/>
</policy> <!-- Include legacy configuration location -->
<include ignore_missing="yes">/etc/dbus-1/system.conf</include> <!-- 包含的子配置文件. -->
<includedir>system.d</includedir> <includedir>/etc/dbus-1/system.d</includedir> <!-- This is included last so local configuration can override what's
in this standard file -->
<include ignore_missing="yes">/etc/dbus-1/system-local.conf</include> <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include> </busconfig>

通过命令行发送dbus消息

dbus支持通过命令发送一个dbus消息,如获取可用的dbus 服务。

dbus-send --session \
--dest=org.freedesktop.DBus \
--type=method_call \
--print-reply \
/org/freedesktop/DBus \
org.freedesktop.DBus.ListNames method return time=1631452206.288425 sender=org.freedesktop.DBus -> destination=:1.29 serial=3 reply_serial=2
array [
string "org.freedesktop.DBus"
string "org.freedesktop.login1"
string "org.freedesktop.systemd1"
string "org.fedoraproject.FirewallD1"
string "org.freedesktop.PolicyKit1"
string ":1.17"
string ":1.0"
string ":1.29"
string ":1.18"
string ":1.1"
]

返回org.freedesktop.DBus service

dbus-send --session \
--dest=org.freedesktop.DBus \
--type=method_call \
--print-reply \
/org/freedesktop/DBus \
org.freedesktop.DBus.Introspectable.Introspect

从需求去理解 Linux dbus与基于dbus协议的无agent软件管理的更多相关文章

  1. 从需求的角度去理解Linux系列:总线、设备和驱动

    笔者成为博客专家后整理以前原创的嵌入式Linux系列博文,现推出以让更多的读者受益. <从需求的角度去理解linux系列:总线.设备和驱动>是一篇有关如何学习嵌入式Linux系统的方法论文 ...

  2. 网络编程[第二篇]基于udp协议的套接字编程

    udp协议下的套接字编程 一.udp是无链接的    不可靠的 而上篇的tcp协议是可靠的,会有反馈信息来确认信息交换的完成与否 基于udp协议写成的服务端与客户端,各司其职,不管对方是否接收到信息, ...

  3. 基于XMPP协议的Android即时通信系

    以前做过一个基于XMPP协议的聊天社交软件,总结了一下.发出来. 设计基于开源的XMPP即时通信协议,采用C/S体系结构,通过GPRS无线网络用TCP协议连接到服务器,以架设开源的Openfn'e服务 ...

  4. 深入理解Linux内存分配

    深入理解Linux内存分配 为了写一个用户层程序,你也许会声明一个全局变量,这个全局变量可能是一个int类型也可能是一个数组,而声明之后你有可能会先初始化它,也有可能放在之后用到它的时候再初始化.除此 ...

  5. 按自己的想法去理解事件和泛型(C#)

    上一篇那些年困扰我们的委托(C#)讲了委托,这一篇自然就轮到事件了. 不喜欢官方的表达方式,喜欢按照自己的想法去理解一些抽象的东西. 事件 考虑到委托使用的一些缺陷,就有了事件.委托是不安全的,打个比 ...

  6. 深入理解 Linux 的 RCU 机制

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:梁康 RCU(Read-Copy Update),是 Linux 中比较重要的一种同步机制.顾名思义就是"读,拷贝更新&quo ...

  7. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

  8. 深入理解 Linux Cgroup 系列(二):玩转 CPU

    原文链接:深入理解 Linux Cgroup 系列(二):玩转 CPU 上篇文章主要介绍了 cgroup 的一些基本概念,包括其在 CentOS 系统中的默认设置和控制工具,并以 CPU 为例阐述 c ...

  9. 深入理解Linux中内存管理

    前一段时间看了<深入理解Linux内核>对其中的内存管理部分花了不少时间,但是还是有很多问题不是很清楚,最近又花了一些时间复习了一下,在这里记录下自己的理解和对Linux中内存管理的一些看 ...

随机推荐

  1. 阿里云RocketMQ定时/延迟消息队列实现

    新的阅读体验:http://www.zhouhong.icu/post/157 一.业务需求 需要实现一个提前二十分钟通知用户去做某件事的一个业务,拿到这个业务首先想到的最简单得方法就是使用Redis ...

  2. YsoSerial 工具常用Payload分析之Common-Collections2、4(五)

    前言 Common-Collections <= 3.2.1 对应与YsoSerial为CC1.3.5.6.7 ,Commno-collections4.0对应与CC2.4. 这篇文章结束官方原 ...

  3. WinUI 3学习笔记(2)—— 用ListView来展示集合

    在WPF的时代,我们多是使用ListBox和ListView来展示,纵向滚动条显示的集合数据.这两个控件的默认样式,以及对触控的支持,已完全落后于时代.他们两个分别长这样,和Win10及Win11的风 ...

  4. 五、从GitHub浏览Prism示例代码的方式入门WPF下的Prism之MVVM中的EventAggregator

    这一篇我们主要再看完示例12.13后,写了个例子,用于再Modules下执行ApplicationCommands,使用IActiveAware执行当前View的Commands,或者Applicat ...

  5. 三年Android开发,竟只会增删改查,被面试官一顿怼!

    最近看到某公司面试官发的这样一个帖子: 我面试了一个有三年Android开发经验的小伙子,也是我有史以来给别人面试时间最短的一次,不到十分钟就结束了,原因很简单,底子太差只会curd,很多技术性的问题 ...

  6. 一、Ocelot简单概述

    以下只是本人学习过程的整理 Ocelot官网:http://threemammals.com/ocelot 说明文档:https://ocelot.readthedocs.io/en/latest/ ...

  7. 给 Arm 生态添把火,腾讯 Kona JDK Arm 架构优化实践

    前言 Arm 架构以其兼具性能与功耗的特点,在智能终端以及嵌入式领域得到了广泛的使用,不断扩大其影响力.而在 PC 端以及数据中心,之前往往是 x86 架构在其中发挥着主要的作用.最近,随着人工智能. ...

  8. 深入理解SPI机制

    一.什么是SPI SPI ,全称为 Service Provider Interface,是一种服务发现机制.它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加 ...

  9. Git-04-本地仓库撤销修改

    编辑修改了文件,但是还没有git add之前 直接用 git checkout -- filename 这个命令就可以了 已经 git add 了,但是没有 git commit 之前 1 模拟git ...

  10. 活久见!TCP两次挥手,你见过吗?那四次握手呢?

    活久见!TCP两次挥手,你见过吗?那四次握手呢? 文章持续更新,可以微信搜一搜「小白debug」第一时间阅读,回复[教程]获golang免费视频教程.本文已经收录在GitHub https://git ...