当前位置: 首页 > ai >正文

Systemd 启动初探

作为linux系统启动重要的组成部分,对systemd 启动流程进行初步探索一下

systemd 是用户空间的 PID 1,它管理系统的服务、cgroup、日志、依赖关系和并行启动。启动流程可以从内核 rest_init() 调用 /sbin/init 开始追踪。这个systemd的binary到底是怎么搞出来的,要干哪些事情,今天研究一下

用户空间入口:PID 1 启动

  • 内核启动完成后,通过 rest_init() 创建 init 进程。

    注意init相关的参数解析

    init=rdinit= 的区别主要体现在 启动源优先级 上:

    init=

    • 指定内核启动后的 用户态第一个程序(PID 1)。

    • 可以是磁盘上的常规程序,例如:

    • init=/sbin/init init=/bin/systemd

    • 内核解析命令行后,会在 rest_init() 里调用 user_mode_thread() 启动该程序。

    • 如果没有指定,内核会尝试默认路径 /sbin/init/etc/init/bin/init

    rdinit=

    • 指定 initramfs 内的初始程序

    • 只在 内核挂载了 initramfs 并且希望从 ramdisk 启动时有效。

    • 例如:

    • rdinit=/init

    • 这个 /init 是 initramfs 文件系统里的 /init 文件,不是磁盘上的。

    • 如果 initramfs 存在,rdinit 优先于 init= 被使用:

      • 内核会先执行 rdinit

      • rdinit 结束后,可能再启动 init= 指定的程序。

    • PID 1 的默认 init 可由内核命令行参数指定:

    • init=/lib/systemd/systemd

    • 如果未指定,内核按 /sbin/init/etc/init 等路径查找。

    • systemd 作为 PID 1,负责初始化整个用户空间。

    systemd 的 main() 是进程启动后最先运行的函数,位于 systemd/src/core/main.c。当它作为 PID 1 启动时,负责从 内核切换到用户空间的第一步管理工作。源码较长,但逻辑可以分为以下几个阶段:

    1. 时间戳与运行环境初始化

    dual_timestamp_from_monotonic(&kernel_timestamp, 0); dual_timestamp_now(&userspace_timestamp); skip_setup = early_skip_setup_check(argc, argv);

    • 记录启动时间戳:保存内核到用户空间的过渡时刻。

    • 判断是否跳过 setup:用于区分首次启动还是重新执行(reexec)。

    • 设置进程名为 systemd,避免因 /sbin/init 链接调用而混淆。

    1. 环境准备与日志初始化

    save_argc_argv(argc, argv); save_env(); log_set_upgrade_syslog_to_journal(true);

    • 保存启动参数和环境变量,便于后续可能的 reexec。

    • 设置日志系统:优先写入 journal;若 PID=1,先临时使用 /dev/kmsg,保证早期日志不会丢失。

    • 容器与宿主机判断detect_container(),决定日志输出到 console 还是 kmsg。

    1. PID 1 特有的早期初始化

    如果 getpid() == 1,说明这是 系统模式(system mode):

    主要工作包括:

    • 挂载早期文件系统(/proc、/sys、/dev),确保能读取 /proc/cmdline

    • 解析内核命令行参数,调整日志或调试选项。

    • 初始化安全模块(SELinux、AppArmor 等)。

    • 加载内核模块(kmod_setup)。

    • 挂载标准 API 文件系统,为后续单元加载做好环境。

    挂载文件系统有挂载表的指导:

    用户模式下:


    1. 配置解析与参数检查

    • 读取 systemd 配置文件(/etc/systemd/system.conf 等)。

    • 解析命令行参数(比如 systemd.unit=, systemd.debug_shell)。

    • 安全检查:确保 cgroup v2 存在,否则报错退出。


    1. Runtime 初始化

    r = initialize_runtime(...); r = manager_new(..., &m); r = manager_startup(m, arg_serialization, fds, NULL);

    • 初始化运行环境(随机数种子、保护系统目录、core dump 设置等)。

    • 创建 Manager 对象:这是 systemd 的“大脑”,维护所有单元(unit)的状态。

    • manager_startup():加载所有 unit 文件,建立依赖关系,准备启动事务。


    1. 默认任务队列与事件循环

    • 创建默认启动任务:一般是 default.target

    • 进入主事件循环:监听 D-Bus、管理进程、执行单元依赖,正式开始调度。

    1. 退出与关机路径

    • 根据返回状态执行相应的退出逻辑:

      • reexec → 重新执行 systemd

      • reboot/poweroff → 调用关机程序

      • exit → 直接退出(主要用于 user mode systemd)

    unit加载:

    http://www.xdnf.cn/news/19231.html

    相关文章:

  • IPv6过渡技术6VPE
  • 【MYSQL】GET_LOCK使用方法简单解析
  • 直线与椭圆相交弦长计算公式
  • 【物联网】BLE Fundamentals 核心概念总结-广告-读写特征-LED控制-传感器通知-上下游通信过程
  • hashmap计算key的hash的时候为什么要右移16位
  • [光学原理与应用-329]:ZEMAX - 主要用途与主要功能
  • 复现 RoboDK 机械臂几何校准(Staubli TX2‑90L / TX200)
  • Redis(自写)
  • MySQL 简介
  • RocketMQ源码详解(NameServer启动流程)
  • Altium Designer中电路板设计
  • 【ICO】快速制作ICON教材/使用icofx3快速制作ico
  • 生成对抗网络(GAN):深度学习领域的革命性突破
  • 深入解析HarmonyOS:UIAbility与Page的生命周期协同
  • var maxScore = Int.MinValue 详解
  • 最长递增子序列(LIS)的 DFS 解法详解与实现
  • 【69页PPT】智慧工厂数字化工厂蓝图规划建设方案(附下载方式)
  • 【计算机组成原理】LRU计数器问题
  • 项目管理的五个阶段是什么
  • 关于PXIe工控机的网速问题XH-PXIe7313万兆网卡
  • Java学习day_14之API(正则表达式)
  • 生成式BI工具(WrenAI)
  • rhel-server-7.9-x86_64-dvd.iso
  • AFSIM仿真工具介绍与源码编译
  • 【开题答辩全过程】以 靖西市旅游网站为例,包含答辩的问题和答案
  • [Oracle] LENGTH()函数
  • php电子签名
  • 【C++】掌握string类操作:高效处理字符串
  • 3D生成模型-NeRF:用神经辐射场定义视图合成
  • Ferris Wheel (贪心 | 双指针)