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仓中):
[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配置文件如下所示:
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
完成子服务的拉起。
-- 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)
组件状态查询命令
在组件运行过程中,可以通过如下命令进行组件状态的查询:
top -cbn 1 # 查看当前启动服务、启动命令、cpu利用率、内存占用率等等
systemctl status # 查看openUBMC的服务启动进程与子进程树状关系
更多系统级信息可以在一键收集日志的dump_info/RTOSDump/sysinfo
中的日志文件查看。
More
更多配置请参考组件实现《hica》