1.说明
openbmc是基于systemd的,dbus的库实现是在systemd。对于用户(app)使用来说,用的是sd-bus相关接口,即lib库,它在systemd中已有提供。系统提供一个总线(dbus daemon),实际是一个进程程序,这个进程程序(dbus的实现dbus-daemon或者dbus-borker的dbus-broker-launcher)会用到systemd实现的库接口,client和server的通信经过这个进程来转发数据,当然,client和server代码的编写也会依赖systemd的库接口。
总体而言,openbmc做了一个sdbusplus的c++ binding,然后该binding使用的是systemd提供的函数接口等。systemd的源码可以参考https://github.com/systemd/systemd. binding简单理解就是c++调用c,其他c++应用程序直接调用binding函数,即是c++层的库。
可以在https://en.wikipedia.org/wiki/D-Bus中找到相关描述:

备注:openbmc 有关dbus的资料:
- 1.https://dbus.freedesktop.org/doc/dbus-specification.html
- 2.https://dbus.freedesktop.org/doc/dbus-tutorial.html
- 3.https://0pointer.net/blog/the-new-sd-bus-api-of-systemd.html
- 4.https://github.com/systemd/systemd
- 5.接口
api:https://github.com/systemd/systemd/blob/main/src/systemd/sd-bus.h - 6.
openbmc实现的sdbus c++ binding: https://github.com/openbmc/sdbusplus
总体而言,对于开发openbmc,可以先看d-bus的基本概念,然后基于此,知道openbmc用到systemd和c++ binding就差不多了。
另外,补充systemd的中文参考手册:
2.openbmc使用的systemd与d-bus说明
参考文章: https://opensource.com/article/20/4/systemd可以看到systemd的架构图:

2.1 openbmc使用的dbus
先使用ast2500平台为例,平台信息如下:

查看dbus使用的daemon服务:

同样,可以使用如下命令查看服务:
# cat /etc/systemd/system/dbus.service

使用命令,均可查看信息:
# cat /lib/systemd/system/dbus-broker.service

另外,也可以观察到系统也包含dbus的实现。

对应,可以查看目录:

谈到这里,可以列出来目前BMC的dbus的实现包含2个:
目前BMC使用的是dbus-borker.
2.2 简单分析一下dbus-broker流程
分析dbu-broker流程前,首先需要阅读2篇文章:
-
1.简单分析一下
dbus-broker-launch代码流程:
src\launch\main.c
int main(int argc, char **argv)
---> r = parse_argv(argc, argv);
---> r = inherit_fds();
---> n = sd_listen_fds(true);
---> s = SD_LISTEN_FDS_START;
---> r = sd_is_socket(s, PF_UNIX, SOCK_STREAM, 1);
---> r = fcntl(s, F_GETFL);
---> r = fcntl(s, F_SETFL, r | O_NONBLOCK);
---> main_fd_listen = s;
---> r = run();
---> r = launcher_new(&launcher, main_fd_listen, main_arg_audit, main_arg_configfile, main_arg_user_scope);
---> r = launcher_open_log(launcher);
---> .sun_path = "/run/systemd/journal/socket",
---> fd = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
---> connect(fd,(struct sockaddr *)&address,offsetof(struct sockaddr_un, sun_path) + strlen(address.sun_path));
---> log_init_journal_consume(&launcher->log, fd);
---> r = sd_event_default(&launcher->event);
---> r = sd_event_add_signal(launcher->event, NULL, SIGTERM, NULL, NULL);
---> r = sd_event_add_signal(launcher->event, NULL, SIGINT, NULL, NULL);
---> r = sd_event_add_signal(launcher->event, NULL, SIGHUP, launcher_on_sighup, launcher);
---> r = sd_bus_new(&launcher->bus_controller);
---> r = launcher_run(launcher);
---> r = launcher_parse_config(launcher, &root, &nss_cache);
---> configfile = "/usr/share/dbus-1/system.conf";
---> config_parser_init(&parser); //XML parser
---> config_parser_read(&parser, rootp, configfile, nss_cache, dirwatch); //解析/usr/share/dbus-1/system.conf
---> r = sd_event_add_io(..., launcher_on_dirwatch,...) //重新加载文件
---> r = launcher_load_services(launcher, root, &nss_cache);
---> r = sd_notify(false, "READY=1");
---> r = launcher_load_policy(launcher, root, &policy);
---> r = socketpair(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, controller); //创建一对双向通信的client/server. 注意是双向通信
---> r = sd_bus_set_fd(launcher->bus_controller, controller[0], controller[0]);
---> bus->input_fd = input_fd; //systemd的代码,输入设置为controller[0]
---> bus->output_fd = output_fd;//systemd的代码,输出均设置为controller[0]
---> r = launcher_fork(launcher, controller[1]); //
---> launcher_run_child(launcher, log_get_fd(&launcher->log), fd_controller);
---> const char * const argv[] = {
"dbus-broker", ...}
---> r = sd_id128_get_machine(&machine_id);
---> sd_id128_to_string(machine_id, str_machine_id);
---> r = execve(main_arg_broker, (char * const *)argv, environ);
---> r = sd_event_add_child(launcher->event, NULL, pid, WEXITED, launcher_on_child_exit, launcher); //建立子进程,在子进程中创建dbus-broker 进程。
---> r = sd_bus_add_object_vtable(launcher->bus_controller, NULL, "/org/bus1/DBus/Controller", "org.bus1.DBus.Controller", launcher_vtable, launcher);
---> r = sd_bus_add_filter(launcher->bus_controller, NULL, launcher_on_message, launcher); //launcher_on_message 是一个很重要的函数
---> r = sd_bus_start(launcher->bus_controller);
---> r = launcher_add_services(launcher);
---> r = launcher_add_listener(launcher, &policy, system_console_users, n_system_console_users);
---> r = launcher_connect(launcher);
---> r = sd_bus_attach_event(launcher->bus_controller, launcher->event, SD_EVENT_PRIORITY_NORMAL);
---> r = sd_bus_attach_event(launcher->bus_regular, launcher->event, SD_EVENT_PRIORITY_NORMAL);
---> r = launcher_subscribe(launcher);
---> r = sd_event_loop(launcher->event);
所以回顾一下之前看到的控制台有2个进程,分别为:/usr/bin/dbus-broker-launch和dbus-broker。其中dbus-broker-launch是由systemd以服务启动的。而dbus-broker则是由如下代码启动起来的。
const char * const argv[] = {
"dbus-broker", ...}
execve(main_arg_broker, (char * const *)argv, environ);
查看文件/usr/lib/systemd/user/dbus.socket的内容:
# cat /usr/lib/systemd/user/dbus.socket
[Unit]
Description=D-Bus User Message Bus Socket
[Socket]
ListenStream=%t/bus
ExecStartPost=-/bin/systemctl --user set-environment DBUS_SESSION_BUS_ADDRESS=unix:path=%t/bus
与文件/lib/systemd/system/dbus-broker.service的内容:
root@ast2500-default:/# cat /lib/systemd/system/dbus-broker
1万+




被折叠的 条评论
为什么被折叠?



