openbmc sdbusplus接口使用(持续更新...)

news2025/2/13 6:39:29

1.说明

本节介绍如何使用sdbusplus,用来对应不同的场景。

可以参考之前的文章: https://blog.csdn.net/wit_yuan/article/details/145192471

建议阅读本篇文章一定要仔细阅读sd-bus specification

2.说明

2.1 简单server服务注册

本节参考: https://gitee.com/wit_yuan/openbmc_testcode/blob/yuan_test_sdbusplus_1/recipe-example/files/test_add_interface.cpp
简单的注册服务,可以只需要使用几个api即可,基本代码如下:

#include <xyz/openbmc_project/net/Calculator/client.hpp>
#include <xyz/openbmc_project/net/Calculator/server.hpp>
#include <sdbusplus/server.hpp>

#include <iostream>
#include <string_view>

#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/property.hpp>

#include <sys/sysinfo.h>
#include <systemd/sd-journal.h>

static std::string busServiceName = "xyz.openbmc_project.test.MyTestService";
int main()
{
    std::shared_ptr<sdbusplus::asio::connection> conn;
    boost::asio::io_context io;
    conn = std::make_shared<sdbusplus::asio::connection>(io);
    conn->request_name(busServiceName.c_str());
    io.run();
    return 0;
}

简单说一下调用实际的功能:

std::make_shared<sdbusplus::asio::connection>(io)

在文件build/evb-ast2500/workspace/sources/sdbusplus/include/sdbusplus/asio/connection.hpp中有定义:

    connection(boost::asio::io_context& io) :
        sdbusplus::bus_t(sdbusplus::bus::new_default()), io_(io),
        socket(io_.get_executor(), get_fd())
    {
        read_immediate();
    }

因此,默认其实调用了函数:

sdbusplus::bus::new_default()

另外:sdbusplus::bus_t(sdbusplus::bus::new_default())实际调用了文件:build/evb-ast2500/workspace/sources/sdbusplus/src/bus.cpp中的函数内容:

bus::bus(busp_t b) :
    _intf(&sdbus_impl),
    _bus(_intf->sd_bus_ref(b), details::BusDeleter(&sdbus_impl))
{
    // Emitting object added causes a message to get the properties
    // which can trigger a 'transaction' in the server bindings.  If
    // the bus isn't up far enough, this causes an assert deep in
    // sd-bus code.  Get the 'unique_name' to ensure the bus is up far
    // enough to avoid the assert.
    if (b != nullptr)
    {
        get_unique_name();
    }
}

因此:

_intf = &sdbus_impl,
_bus = _intf->sd_bus_ref(b)

在文件build/evb-ast2500/workspace/sources/sdbusplus/include/sdbusplus/sdbus.hpp:中可以看到:

class SdBusImpl : public SdBusInterface
{
int sd_bus_add_object_manager(...)
int sd_bus_add_object_vtable(...)
int sd_bus_add_match(...)
int sd_bus_attach_event( ...)
int sd_bus_call(...)
int sd_bus_call_async(...)
int sd_bus_detach_event(...)
int sd_bus_emit_interfaces_added_strv(...)
...
int sd_bus_emit_object_added(...)
int sd_bus_get_fd(...)
int sd_bus_message_enter_container(...)
sd_bus* sd_bus_message_get_bus(...)
const char* sd_bus_message_get_interface(...)
const char* sd_bus_message_get_path(...)
int sd_bus_message_is_method_call(..)
int sd_bus_message_new_method_call(...)
int sd_bus_message_new_signal(...)
int sd_bus_process(...)
int sd_bus_request_name(...)
void sd_bus_close(...)
int sd_bus_is_open(...)
int sd_bus_wait(...)
}
extern SdBusImpl sdbus_impl;

以及文件:build/evb-ast2500/workspace/sources/sdbusplus/src/sdbus.cpp中定义的:

#include <sdbusplus/sdbus.hpp>

namespace sdbusplus
{
SdBusImpl sdbus_impl;
}

包含的均为sd-bus接口的调用封装。

注意函数read_immediate()调用函数:

    void read_immediate()
    {
        boost::asio::post(io_, [&] {
            if (process_discard())
            {
                read_immediate();
            }
            else
            {
                read_wait();
            }
        });
    }

因此,函数调用:

conn->request_name(busServiceName.c_str());

实际执行了文件build/evb-ast2500/workspace/sources/sdbusplus/include/sdbusplus/bus.hpp中的:

    void request_name(const char* service)
    {
        int r = _intf->sd_bus_request_name(
            _bus.get(), service,
            (SD_BUS_NAME_ALLOW_REPLACEMENT | SD_BUS_NAME_REPLACE_EXISTING));
        if (r < 0)
        {
            throw exception::SdBusError(-r, "sd_bus_request_name");
        }
    }

qemu启动之后,可以看到这个例子只是一个简单的例子,并无实际的意义,因为并不能找到相关的接口功能。执行结果如下:

在这里插入图片描述

2.2 添加接口

添加接口与相关的属性,才具初始的功能。

先分析2行代码:

    sdbusplus::asio::object_server obj_server = sdbusplus::asio::object_server(conn);
    Iface = obj_server.add_interface("/org/freedesktop" , busServiceName); 
    Iface->initialize();

在文件:build/evb-ast2500/workspace/sources/sdbusplus/include/sdbusplus/asio/object_server.hpp中定义了:

    object_server(const std::shared_ptr<sdbusplus::asio::connection>& conn,
                  const bool skipManager = false) : conn_(conn)
    {
        if (!skipManager)
        {
            add_manager("/");
        }
    }

因此默认skipManager = false,会调用add_manager("/");

Iface = obj_server.add_interface("/org/freedesktop" , busServiceName);

调用文件:build/evb-ast2500/workspace/sources/sdbusplus/include/sdbusplus/asio/object_server.hpp中的函数:

    std::shared_ptr<dbus_interface>
        add_interface(const std::string& path, const std::string& name)
    {
        auto dbusIface = std::make_shared<dbus_interface>(conn_, path, name);
        interfaces_.emplace_back(dbusIface);
        return dbusIface;
    }

只需要注意:interfaces_是被定义在类中的私有变量:

  private:
    std::shared_ptr<sdbusplus::asio::connection> conn_;
    std::vector<std::shared_ptr<dbus_interface>> interfaces_;
    std::vector<server::manager_t> managers_;

另外,dbus_interface有在build/evb-ast2500/workspace/sources/sdbusplus/include/sdbusplus/asio/object_server.hpp中定义了:

    dbus_interface(std::shared_ptr<sdbusplus::asio::connection> conn,
                   const std::string& path, const std::string& name) :
        conn_(conn), path_(path), name_(name)

    {}

所以,在这里只完成了基本的赋值与将定义的接口放入vector(数组)中。

最后,需要调用:Iface->initialize();,可以看到调用了文件build/evb-ast2500/workspace/sources/sdbusplus/include/sdbusplus/asio/object_server.hpp中的:

    bool initialize(const bool skipPropertyChangedSignal = false)
    {
        // can only register once
        if (is_initialized())
        {
            return false;
        }
        vtable_.reserve(2 + property_callbacks_.size() +
                        method_callbacks_.size() + signals_.size());
        vtable_.emplace_back(vtable::start());
        property_callbacks_.shrink_to_fit();
        for (auto& element : property_callbacks_)
        {
            if (element.on_set_message_)
            {
                vtable_.emplace_back(vtable::property_o(
                    element.name_.c_str(), element.signature_, get_handler,
                    set_handler, reinterpret_cast<size_t>(&element),
                    element.flags_ | SD_BUS_VTABLE_ABSOLUTE_OFFSET));
            }
            else
            {
                vtable_.emplace_back(vtable::property_o(
                    element.name_.c_str(), element.signature_, get_handler,
                    reinterpret_cast<size_t>(&element),
                    element.flags_ | SD_BUS_VTABLE_ABSOLUTE_OFFSET));
            }
        }

        method_callbacks_.shrink_to_fit();
        for (auto& element : method_callbacks_)
        {
            vtable_.emplace_back(vtable::method_o(
                element.name_.c_str(), element.arg_signature_,
                element.return_signature_, method_handler,
                reinterpret_cast<size_t>(&element),
                element.flags_ | SD_BUS_VTABLE_ABSOLUTE_OFFSET));
        }

        signals_.shrink_to_fit();
        for (const auto& element : signals_)
        {
            vtable_.emplace_back(
                vtable::signal(element.name_.c_str(), element.signature_));
        }

        vtable_.emplace_back(vtable::end());
        vtable_.shrink_to_fit();

        interface_.emplace(static_cast<sdbusplus::bus_t&>(*conn_),
                           path_.c_str(), name_.c_str(),
                           static_cast<const sd_bus_vtable*>(&vtable_[0]),
                           nullptr);
        conn_->emit_interfaces_added(path_.c_str(),
                                     std::vector<std::string>{name_});
        if (!skipPropertyChangedSignal)
        {
            for (const auto& element : property_callbacks_)
            {
                signal_property(element.name_);
            }
        }
        return true;
    }

另外,分析一下内容:

vtable_.reserve(2 + property_callbacks_.size() +
                        method_callbacks_.size() + signals_.size());

可以看到代码是在vtable是针对propertymethodsignals的执行操作,由于SD_BUS_VTABLE_START(0)SD_BUS_VTABLE_END占用2个空间,故加2。

这一节的代码参考: https://gitee.com/wit_yuan/openbmc_testcode/blob/yuan_add_interface/recipe-example/files/test_add_interface.cpp

需要之前的hello服务器程序运行起来。

在这里插入图片描述
同样,可以看到设置和获取property值的变化:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2297217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.12寒假作业

web&#xff1a;[HDCTF 2023]Welcome To HDCTF 2023 可以直接玩出来 但是这边还是看一下怎么解吧&#xff0c;看一下js代码&#xff0c;在js.game里面找到一个类似brainfuck加密的字符串 解密可以得到答案&#xff0c;但是后面我又去了解了一下let函数let命令、let命令 let命…

GitHub项目推荐--适合练手的13个C++开源项目

1 C 那些事 这是一个适合初学者从入门到进阶的仓库&#xff0c;解决了面试者与学习者想要深入 C及如何入坑 C的问题。 除此之外&#xff0c;本仓库拓展了更加深入的源码分析&#xff0c;多线程并发等的知识&#xff0c;是一个比较全面的 C 学习从入门到进阶提升的仓库。 项目…

【2025 Nature】AI 生成材料算法 MatterGen 文章要点

文章目录 1. MatterGen 框架2. 评价基础模型生成能力的指标3. MatterGen 基础生成能力表现4. MatterGen 定向生成能力表现i. 指定晶体化学式ii. 指定标量性质1. 每个性质微调一次。2. 两个性质联合微调 5. 实验合成6. 模型细节 这篇文档简单介绍 MatterGen 论文亮点。 标题&…

时间序列分析(三)——白噪声检验

此前篇章&#xff1a; 时间序列分析&#xff08;一&#xff09;——基础概念篇 时间序列分析&#xff08;二&#xff09;——平稳性检验 一、相关知识点 白噪声的定义&#xff1a;白噪声序列是一种在统计学和信号处理中常见的随机过程&#xff0c;由一系列相互独立、具有相同…

[前端] axios网络请求二次封装

一、场景描述 为什么要对axios网络请求进行二次封装? 解决代码的复用&#xff0c;提高可维护性。 —这个有两个方案&#xff1a;一个是二次封装一个是实例化。&#xff08;设置一些公共的参数&#xff0c;然后进行请求&#xff09; 为什么可以解决代码的复用&#xff1a; 这是…

【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】CSS样式解析:行内、内部与外部样式的区别与优先级分析

简介 2025年计算机视觉研究进展与应用&#xff08;ACVRA 2025&#xff09;将于2025年2月28-3月2日在中国广州召开&#xff0c;会议将汇聚世界各地的顶尖学者、研究人员和行业专家&#xff0c;聚焦计算机视觉领域的最新研究动态与应用成就。本次会议将探讨前沿技术&#xff0c;…

麒麟信安系统隔核后iperf网络测试影响说明

1、背景介绍 采用麒麟信安系统&#xff0c;在飞腾平台&#xff08;X86平台类似&#xff09;上进行了系统核隔离&#xff0c;修改了grub.cfg配置文件中的启动项增加isolcpus2-63 操作&#xff0c;隔核后发现40G网络iperf测试存在影响。 测试命令 taskset -c 16-23 iperf -s -…

WPF进阶 | WPF 资源管理与本地化:多语言支持与资源复用

WPF进阶 | WPF 资源管理与本地化&#xff1a;多语言支持与资源复用 前言一、WPF 资源管理基础1.1 什么是 WPF 资源1.2 资源的定义与存储位置1.3 资源的引用方式 二、资源字典的深入应用2.1 创建资源字典2.2 在应用程序中合并资源字典2.3 资源字典的层级结构与合并顺序 三、WPF …

数据结构与算法-动态规划-区间dp(石子合并,环形石子合并,凸多边形的划分,加分二叉树,棋盘分割)

概念 区间动态规划&#xff08;Interval Dynamic Programming&#xff09;是动态规划的一个分支&#xff0c;它在处理一些与区间相关的最优解问题上非常有效。以下从基本概念、解题步骤、经典例题、优缺点等方面为你详细介绍&#xff1a; 基本概念&#xff1a;区间 DP 的核心…

32单片机学习记录4之串口通信

32单片机学习记录4之串口通信 前置 STM32的GPIO口有通用模式&#xff0c;复用模式&#xff0c;模拟模式三种&#xff0c;加上输入输出就是有6中对应的模式。 我学习了通用模式&#xff0c;会使用GPIO口使用一些简单外设&#xff0c;如LED&#xff0c;独立按键&#xff0c;红外…

开源、免费项目管理工具比较:2025最新整理30款

好用的开源、免费版项目管理系统有&#xff1a;1.Redmine&#xff1b;2. Taiga&#xff1b;3. OpenProject&#xff1b; 4.ProjectLibre&#xff1b; 5.GanttProject&#xff1b; 6.Tuleap&#xff1b; 7.Trac&#xff1b;8. Phabricator&#xff1b; 9.Notion&#xff1b; 10.…

Android10 音频参数导出合并

A10 设备录音时底噪过大&#xff0c;让音频同事校准了下&#xff0c;然后把校准好的参数需要导出来&#xff0c;集成到项目中&#xff0c;然后出包&#xff0c;导出方式在此记录 设备安装debug系统版本调试好后&#xff0c; adb root adb remount adb shell 进入设备目录 导…

在 Azure 上部署 DeepSeek 并集成 Open WebUI

DeepSeek 是杭州深度求索人工智能基础技术研究有限公司发布的开源大模型&#xff0c;最近是持续火爆&#xff0c;使得官方服务经常不可用。网上各种本地部署和私有部署的文章已经很多&#xff0c;这里我们提供一个全部基于 Azure 的私有部署方案。 使用 Azure AI Foundry 部署…

Springboot整合支付宝支付

支付宝支付功能 步骤一&#xff1a;沙箱配置支付宝沙箱配置 步骤二&#xff1a;使用内网穿透步骤三&#xff1a;开始对接SDK配置文件支付 步骤一&#xff1a;沙箱配置 支付宝沙箱配置 需要有支付宝沙箱&#xff1a;提供一个虚拟的支付环境&#xff0c;用于测验调试&#xff0…

deepseek+kimi一键生成PPT

1、deepseek生成大纲内容 访问deepseek官方网站&#xff1a;https://www.deepseek.com/ 将你想要编写的PPT内容输入到对话框&#xff0c;点击【蓝色】发送按钮&#xff0c;让deepseek生成内容大纲&#xff0c;并以markdown形式输出。 等待deepseek生成内容完毕后&#xff0c…

基于ssm的超市订单管理系统

一、系统架构 前端&#xff1a;jsp | web components | jquery | css | ajax 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.8 | mysql | maven | tomcat 二、代码及数据 三、功能介绍 01. 登录 02. 首页 03. 订单管理 04. 供应…

AnyPlace:学习机器人操作的泛化目标放置

25年2月来自多伦多大学、Vector Inst、上海交大等机构的论文“AnyPlace: Learning Generalized Object Placement for Robot Manipulation”。 由于目标几何形状和放置的配置多种多样&#xff0c;因此在机器人任务中放置目标本身就具有挑战性。为了解决这个问题&#xff0c;An…

【DeepSeek】在本地计算机上部署DeepSeek-R1大模型实战(完整版)

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能&#xff08;AI&#xff09;通过算法模拟人类智能&#xff0c;利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络&#xff08;如ChatGPT&…

基于全志T507的边缘计算机,推动光伏电站向智能运维转型

智能监控与维护 光伏电站通常分布在广阔的地域内&#xff0c;传统的监控方式往往需要大量的人力物力进行现场检查和数据采集。采用全志T507为核心的嵌入式工控机或边缘计算控制器可以实现光伏电站的实时监测&#xff0c;通过连接传感器网络收集电站各个组件的工作状态信息&…

用户认证练习实验

一.拓扑 二.sw2配置 三.ip配置 四.dhcp分配IP地址 五.安全区域配置 六.防火墙地址组信息 七.管理员 创建管理员角色 创建管理员 启动tenlnet 八.用户认证配置 认证策略 九.安全策略配置