NOTEBOOK

sysMaster

源码仓库:https://gitee.com/openeuler/sysmaster

0-背景

Linux的启动流程大致如下:

  1. BIOS:硬件检测,查找并加载磁盘上的MBR
  2. MBR:存储BootLoader信息,加载GRUB
  3. GRUB:查找并加载Kernal
  4. Kernal:装载驱动,挂载rootfs,执行/sbin/init
  5. Init:OS初始化,执行runlevel相关程序
  6. Runlevel:启动指定级别的服务

MBR:MBR(Master Boot Record)是硬盘上一段重要的引导代码区域,位于硬盘的第一个扇区(通常是第0号扇区,即第512字节的位置)。这个扇区包含了引导加载程序(boot loader)以及分区表(partition table),用于告诉计算机操作系统的位置。

GRUB:GRUB(GNU GRand Unified Bootloader)是一种广泛使用的引导加载程序(boot loader),主要用于 Unix-like 操作系统,如 Linux 和 BSD。

Init是OS的初始化过程,最常见的就是systemd,但是其代码量大并且性能一般,所以有了sysMaster

1-sysMaster

sysMaster共有init、core、exts三个部分:

1-0 init

// main函数位于sysmaster/init/main.rs
fn main() -> std::io::Result<()> {
    setup_mount_early();

    log::init_log_to_kmsg_console("sysmaster-init", log::Level::Info);

    prepare_init();

    reset_all_signal_handlers();
    install_crash_handler();

    let mut rt = Runtime::new()?;
    rt.set_state(InitState::Running);

    rt.runloop()?;

    if rt.is_reexec() {
        rt.reexec();
    }
    shutdown_init();
    Ok(())
}

1-1 core

core部分实现了很多核心功能,这里拿sctl(systemctl)为例:

// main函数位于sysmaster/core/sctl/src/main.rs
fn main() {
    let args = parse_args();

    let command_request = match generate_command_request(args) {
        None => {
            eprintln!("This command is currently not supported");
            exit(nix::Error::ENOTSUP as i32);
        }
        Some(v) => v,
    };

    let stream = match UnixStream::connect(PRIVATE_SOCKET) {
        Err(e) => {
            eprintln!("Failed to connect to sysmaster: {}", e);
            exit(e.raw_os_error().unwrap());
        }
        Ok(v) => v,
    };

    let mut client = ProstClientStream::new(stream);

    let data = match client.execute(command_request) {
        Err(e) => {
            eprintln!("Failed to execute the given command: {}", e);
            exit(1);
        }
        Ok(v) => v,
    };

    /* We should always print the error message if the returned error code is not 0. */
    if data.message.is_empty() {
        exit(0);
    }

    if data.error_code == 0 || (data.error_code & ERROR_CODE_MASK_PRINT_STDOUT != 0) {
        /* Don't care if we fail to write the message out. */
        let _ = writeln!(std::io::stdout(), "{}", data.message);
    } else {
        eprintln!("{}", data.message);
    }

    exit((data.error_code & !ERROR_CODE_MASK_PRINT_STDOUT) as i32);
}

1-2 exts

exts下有devmaster(设备初始化和管理)、fstab(定义系统上的文件系统如何挂载)、getty-generator(生成getty配置或脚本的工具,getty用来初始化终端登录)、hostname_setup(配置主机名)、hwdb(硬件数据库)、libudev(设备管理器的库文件)、libudev_macro(支持libudev使用)、machine-id-setup(生成机器唯一标识符)、random_seed(随机数生成器)、rc-local-generator(Linux启动脚本)、run(存放运行时状态)、switch_root(与切换根文件系统相关)和sysmonitor(监控系统状态)

这里以random_seed为例:

// main函数位于sysmaster/exts/random_seed/src/main.rs
fn main() {
    log::init_log_to_console_syslog("random-seed", log::Level::Debug);
    let args: Vec<String> = env::args().collect();
    if args.len() != 2 {
        log::error!("{}", "This program requires one argument.");
        process::exit(1);
    }

    unsafe {
        libc::umask(0o022);
    }

    if let Err(str) = run(&args[1]) {
        log::error!("{}", str);
        process::exit(1);
    }

    process::exit(0);
}