组件启动配置
更新时间:2024/12/19
在Gitcode上查看源码

openUBMC采用了先进的微组件开发架构,将BMC管理的资源抽象成资源对象,组件通过资源接口标准相互通信,启动过程采用层级内并行拉起,可快速拉起openUBMC整套服务。

openUBMC启动框架

openUBMC的启动框架采用*Systemd+Skynet实现。其中服务的启动借助Systemd完成。Systemd作为一个Linux系统的初始化系统和系统管理器,负责启动系统中的各种服务和进程,并管理它们的生命周期。通过Systemd,openUBMC能够轻松地监控服务状态、控制服务的启动和停止,以及以进程为单位管理子服务的日志记录和用户管理。

除此之外,openUBMC采用了Skynet作为底层运行框架,Skynet是使用C+lua实现的一个轻量级服务器框架,能够将一个数据包从一个服务内发送初期,让同一进程内的服务收到并调用对应的callback函数处理。

openUBMC的服务启动特点

  • 并行启动:传统的初始化系统采用串行启动方式,即按照固定的顺序逐个启动服务。而systemd采用并行启动方式,可以同时启动多个服务,大大提高了系统启动速度。
  • 依赖管理:systemd使用了一种基于依赖关系的服务启动方式。通过定义服务之间的依赖关系,systemd可以确保服务在正确的顺序下启动,并自动处理服务之间的依赖冲突。
  • 子服务拉起:采用Skynet完成单个进程服务内的子服务拉起。服务与服务之间环境解耦,减少服务之间的冲突。
  • 灵活配置: openUBMC采用Systemd执行Skynet,此过程也可以自定义Systemd执行非Skynet命令以启动定制化服务。
  • 独立重启:服务或服务出现异常,若无其他依赖项,无需执行openUBMC全量重启,只需重启单服务即可。

openUBMC 启动流程

Systemd拉起服务

openUBMC的启动服务使用Systemd并行拉起服务(采用执行Skynet+配置文件方式拉起),整个流程中通过定义启动顺序和依赖项完成服务拉起。以bmc_core服务的拉起为例(所有的Systemd配置都在hica仓中):

lua
[Unit]
Description=bmc_core service 
After=framework.service 
Requires=dbus.service framework.service 

[Service]
StandardOutput=tty
TTYPath=/dev/ttyS0
User=root  
Restart=always  
RestartSec=2   
StartLimitInterval=0
EnvironmentFile=/dev/shm/dbus/.dbus  
Environment="ROOT_DIR="
Environment="PROJECT_DIR="
WorkingDirectory=/opt/bmc/apps/hica
ExecStartPre=/bin/bash -c "uptime=`/bin/cat /proc/uptime |awk -F '.' '{print $1}'`; if [ $uptime -lt 100 ]; then /bin/sleep 30; fi"
ExecStart=bash -c 'exec -a bmc_core /opt/bmc/skynet/skynet /opt/bmc/apps/hica/subsys/bmc_core/config.cfg'
ExecStartPost=/bin/bash -c 'echo 0x21 > /proc/$MAINPID/coredump_filter'
KillMode=process
MemoryHigh=1000M
MemoryMax=1024M
LimitCORE=100000000
LimitSTACK=100000000

[Install]
WantedBy=multi-user.target

以上配置为Systemd的配置,具体配置请参考Systemd

Unit:服务单元描述
Unit.Description:服务进程描述
Unit.After:服务拉起时序,在指定服务拉起后才能拉起
Unit.Requires:服务拉起时序,当依赖项重启时,本服务也会被重启
Service: 服务环境配置与约束
Service.User: 服务启动账户声明
Service.Restart: 服务重启模式
Service.RestartSec: 服务重启时延,单位秒
Service.StartLimitInterval: 无限次重启设置
Service.Environmentxxx: 环境变量配置
Service.WorkingDirectory: 服务工作路径(最终在服务器中的位置)
Service.ExecStartPre: 服务拉起预处理,通过抓取uptime中的信息进行时延启动
Service.ExecStart: 服务拉起命令,通过bash运行Skynet及其配置文件完成服务的拉起
Service.ExecStartPost: 服务拉起后处理
Service.KillMode: 设置在该单元服务停止时,杀死进程的方法
Service.MemoryHigh: 内存使用限制,如果进程的内存超过该限制,进程将会被降低运行时间,并快速回收其占用的内存
Service.MemoryMax: 内存最大使用限制,如果进程的内存超过该限制,则会触发out of memeory将其kill掉
Service.LimitCORE: 用于设置服务进程可创建的核心转储(core dump)的最大大小
Service.LimitSTACK:设置服务进程的栈大小限制
Install: 定义服务安装位置
Install.WantBy: 定义服务启动的拉起目标

在启动配置中,明确了服务启动的顺序、依赖服务、服务用户权限、服务重启模式、以及服务启动前置条件和服务执行命令

Skynet拉起子服务

在上述描述中,我们知道Systemd会拉起一个个的进程服务,但本质上服务的拉起还是执行特定配置文件条件下的Skynet服务。在配置文件中定义了Skynet的所需的执行入口、执行环境、拉起子服务的定义。bmc_core配置文件如下所示:

lua
include "/opt/bmc/libmc/config.cfg"

config:set_root("/")
config:set_start("hica/subsys/bmc_core/service/main")  
config:include_app("firmware_mgmt")  
config:include_app("bmc_upgrade") 
...
config:include_app("ipmi_core")
config:done()

MODULE_NAME = "bmc_core"  -- 服务名
thread = 6 -- 线程配置

... -- 环境配置

OPERATE_LOG_PATH = '/var/log/operate_log'

include:基础配置文件的引入
config:set_root: 设置root路径
config:set_start: 服务启动程序入口
config:include_app: 服务启动包含组件的路径申明
config:done(): 结束config配置申明
MODULE_NAME:启动模块名
thread: 启动线程数

在本配置文件中完成了服务的入口的定义,在此配置下,进入到hica/subsys/bmc_core/service/main执行Skynet的fork完成子服务的拉起。

lua
-- hica/subsys/hardware/service/main
local skynet = require 'skynet'
local launch_control = require 'mc.launch_control'


skynet.start(function()
    local module_name = skynet.getenv('MODULE_NAME')
    ...
    skynet.uniqueservice('sd_bus')  -- sd_bus服务拉起
    launch_control.launch_components('bmc_core')  -- bmc_core子服务拉起
end)

组件状态查询命令

在组件运行过程中,可以通过如下命令进行组件状态的查询:

shell
top -cbn 1 # 查看当前启动服务、启动命令、cpu利用率、内存占用率等等
shell
systemctl status # 查看openUBMC的服务启动进程与子进程树状关系

更多系统级信息可以在一键收集日志的dump_info/RTOSDump/sysinfo中的日志文件查看。

More

更多配置请参考组件实现《hica》