|
|
|
|
挪动端

对通博8888官网零碎启动进程剖析

关于开源软件最陈旧的笑话是:“代码是自具文档化的”。经历标明,阅读源代码就像听气候预告一样:明智的人仍然出门会看看室外的气候。本文报告了怎样运用调试东西来察看和剖析 通博8888官网 零碎的启动。剖析一个功用正常的零碎启动进程,有助于用户和开辟职员应对不行防止的毛病。

作者:Alison Chaiken泉源:通博8888官网中国|2018-03-13 13:00

【新品产上线啦】51CTO播客,随时随地,碎片化学习

对通博8888官网零碎启动进程剖析

了解运转精良的零碎关于处置不行防止的毛病是最好的预备。

关于开源软件最陈旧的笑话是:“代码是自具文档化的self-documenting”。经历标明,阅读源代码就像听气候预告一样:明智的人仍然出门会看看室外的气候。本文报告了怎样运用调试东西来察看和剖析 通博8888官网 零碎的启动。剖析一个功用正常的零碎启动进程,有助于用户和开辟职员应对不行防止的毛病。

从某些方面看,启动进程十分复杂。内核在单核上以单线程和同步形态启动,好像可以了解。但内核自身是怎样启动的呢?initrd(initial ramdisk)引导顺序bootloader具有哪些功用?另有,为什么以太网端口上的 LED 灯是常亮的呢?

请持续阅读寻觅答案。在 GitHub 上也提供了 引见演示和训练的代码

启动的开端:OFF 形态 

局域网叫醒Wake-on-LAN

OFF 形态表现零碎没有上电,没错吧?外表复杂,实在否则。比方,假如零碎启用结果域网叫醒机制(WOL),以太网指示灯将亮起。经过以下下令来反省能否是这种状况:

  1. # sudo ethtool <interface name>

此中 <interface name> 是网络接口的名字,比方 eth0。(ethtool 可以在同名的 通博8888官网 软件包中找到。)假如输入中的 Wake-on 表现 g,则近程主机可以经过发送 邪术数据包MagicPacket 来启动零碎。假如您有意近程叫醒零碎,也不盼望其别人如许做,请在零碎 BIOS 菜单中将 WOL 封闭,或许用以下方法:

  1. # sudo ethtool -s <interface name> wol d

呼应邪术数据包的处置器能够是网络接口的一局部,也能够是 底板办理控制器Baseboard Management Controller(BMC)。

英特尔办理引擎、平台控制器单位和 Minix

BMC 不是独一的在零碎封闭时仍在监听的微控制器(MCU)。x86_64 零碎还包括了用于近程办理零碎的英特尔办理引擎(IME)软件套件。从效劳器到条记本电脑,林林总总的设置装备摆设都包括了这项技能,它开启了如 KVM 近程控制和英特尔功用答应效劳等 功用。依据 Intel 本人的检测东西IME 存在尚未修补的破绽。坏音讯是,要禁用 IME 很难。Trammell Hudson 提倡了一个 me_cleaner 项目,它可以肃清一些绝对恶劣的 IME 组件,比方嵌入式 Web 效劳器,但也能够会影响运转它的零碎。

IME 固件和零碎办理形式System Management Mode(SMM)软件是 基于 Minix 操纵零碎 的,并运转在独自的平台控制器单位Platform Controller Hub上(LCTT 译注:即南桥芯片),而不是主 CPU 上。然后,SMM 启动位于主处置器上的通用可扩展固件接口Universal Extensible Firmware Interface(UEFI)软件,相干内容 已被提及屡次。Google 的 Coreboot 小组曾经启动了一个雄心壮志的 非扩展性缩减版固件Non-Extensible Reduced Firmware(NERF)项目,其目标不只是要代替 UEFI,还要代替晚期的 通博8888官网 用户空间组件,如 systemd。在我们等候这些新效果的同时,通博8888官网 用户如今就可以从 Purism、System76 或 Dell 等处购置 禁用了 IME 的条记本电脑,别的 带有 ARM 64 位处置器条记本电脑 照旧值得等待的。

引导顺序

除了启动那些题目不时的特务软件外,晚期引导固件另有什么功用呢?引导顺序的作用是为新上电的处置器提供通用操纵零碎(如 通博8888官网)所需的资源。在开机时,不光没有假造内存,在控制器启动之前连 DRAM 也没有。然后,引导顺序翻开电源,并扫描总线和接口,以定位内核镜像和根文件零碎的地位。U-Boot 和 GRUB 等罕见的引导顺序支持 USB、PCI 和 NFS 等接口,以及更多的嵌入式公用设置装备摆设,如 NOR 闪存和 NAND 闪存。引导顺序还与 可信平台模块Trusted Platform Module(TPM)等硬件平安设置装备摆设停止交互,在启动最开端树立信托链。

在构建主机上的沙盒中运转 U-boot 引导顺序。

在构建主机上的沙盒中运转 U-boot 引导顺序。

包罗树莓派、任地狱设置装备摆设、汽车主板和 Chromebook 在内的零碎都支持普遍运用的开源引导顺序 U-Boot。它没有零碎日记,当发作题目时,乃至没有任何控制台输入。为了便于调试,U-Boot 团队提供了一个沙盒,可以在构建主机乃至是夜间的继续集成(CI)零碎上测试补丁顺序。假如零碎上装置了 Git 和 GNU Compiler Collection(GCC)等通用的开辟东西,运用 U-Boot 沙盒会绝对复杂:

  1. # git clone git://git.denx.de/u-boot; cd u-boot
  2. # make ARCH=sandbox defconfig
  3. # make; ./u-boot
  4. => printenv
  5. => help

在 x86_64 上运转 U-Boot,可以测试一些顺手的功用,如 模仿存储设置装备摆设 的重新分区、基于 TPM 的密钥操纵以及 USB 设置装备摆设热插拔等。U-Boot 沙盒乃至可以在 GDB 调试器下单步实行。运用沙盒停止开辟的速率比将引导顺序革新到电路板上的测试快 10 倍,而且可以运用 Ctrl + C 规复一个“变砖”的沙盒。

启动内核 

设置装备摆设引导内核

引导顺序完成义务后将跳转到已加载到主内存中的内核代码,并开端实行,通报用户指定的任何下令行选项。内核是什么样的顺序呢?用下令 file /boot/vmlinuz 可以看到它是一个 “bzImage”,意思是一个大的紧缩的镜像。通博8888官网 源代码树包括了一个可以解紧缩这个文件的东西—— extract-vmlinux

  1. # scripts/extract-vmlinux /boot/vmlinuz-$(uname -r) > vmlinux
  2. # file vmlinux
  3. vmlinux: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically
  4. linked, stripped

内核是一个 可实行与可链接款式 Executable and Linking Format(ELF)的二进制文件,就像 通博8888官网 的用户空间顺序一样。这意味着我们可以运用 binutils 包中的下令,如 readelf 来反省它。比拟一下输入,比方:

  1. # readelf -S /bin/date
  2. # readelf -S vmlinux

这两个二进制文件中的段内容大抵相反。

以是内核必需像其他的 通博8888官网 ELF 文件一样启动,但用户空间顺序是怎样启动的呢?在 main() 函数中?并不确切。

main() 函数运转之前,顺序需求一个实行上下文,包罗货仓内存以及 stdiostdoutstderr 的文件描绘符。用户空间顺序从规范库(少数 通博8888官网 零碎在用 “glibc”)中获取这些资源。参照以下输入:

  1. # file /bin/date
  2. /bin/date: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
  3. linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/通博8888官网 2.6.32,
  4. BuildID[sha1]=14e8563676febeb06d701dbee35d225c5a8e565a,
  5. stripped

ELF 二进制文件有一个表明器,就像 Bash 和 Python 剧本一样,但是表明器不需求像剧本那样用 #! 指定,由于 ELF 是 通博8888官网 的原生款式。ELF 表明器经过挪用 _start() 函数来用所需资源 设置装备摆设一个二进制文件,这个函数可以从 glibc 源代码包中找到,可以 用 GDB 检查。内核显然没有表明器,必需自我设置装备摆设,这是怎样做到的呢?

用 GDB 反省内核的启动给出了答案。起首装置内核的调试软件包,内核中包括一个未剥离的unstripped vmlinux,比方 apt-get install linux-image-amd64-dbg,或许从源代码编译和装置你本人的内核,可以参照 Debian Kernel Handbook 中的指令。gdb vmlinux 后加 info files 可表现 ELF 段 init.text。在 init.text 中用 l *(address) 列出顺序实行的扫尾,此中 addressinit.text 的十六进制扫尾。用 GDB 可以看到 x86_64 内核从内核文件 arch/x86/kernel/head_64.S 开端启动,在这个文件中我们找到了汇编函数 start_cpu0(),以及一段明白的代码表现在挪用 x86_64 start_kernel() 函数之前创立了货仓并解压了 zImage。ARM 32 位内核也有相似的文件 arch/arm/kernel/head.Sstart_kernel() 不针对特定的体系构造,以是这个函数驻留在内核的 init/main.c 中。start_kernel() 可以说是 通博8888官网 真正的 main() 函数。

从 start_kernel() 到 PID 1 

内核的硬件清单:设置装备摆设树和 ACPI 表

在引导时,内核需求硬件信息,不只仅是已编译过的处置器范例。代码中的指令经过独自存储的设置装备摆设数据停止扩大。有两种次要的数据存储办法:设置装备摆设树device-tree初级设置装备摆设和电源接口(ACPI)表。内核经过读取这些文件理解每次启动时需求运转的硬件。

关于嵌入式设置装备摆设,设置装备摆设树是已装置硬件的清单。设置装备摆设树只是一个与内核源代码同时编译的文件,通常与 vmlinux 一样位于 /boot 目次中。要检查 ARM 设置装备摆设上的设置装备摆设树的内容,只需对称号与 /boot/*.dtb 婚配的文件实行 binutils 包中的 strings 下令即可,这里 dtb 是指设置装备摆设树二进制文件device-tree binary。显然,只需编辑组成它的类 JSON 的文件偏重新运转随内核源代码提供的特别 dtc 编译器即可修正设置装备摆设树。固然设置装备摆设树是一个静态文件,其文件途径通常由下令行引导顺序通报给内核,但比年来添加了一个 设置装备摆设树掩盖 的功用,内核在启动后可以静态加载热插拔的附加设置装备摆设。

x86 系列和很多企业级的 ARM64 设置装备摆设运用 ACPI 机制。与设置装备摆设树差别的是,ACPI 信息存储在内核在启动时经过拜访板载 ROM 而创立的 /sys/firmware/acpi/tables 假造文件零碎中。读取 ACPI 表的复杂办法是运用 acpica-tools 包中的 acpidump 下令。比方:

遐想条记本电脑的 ACPI 表都是为 通博8888 2001 设置的。

遐想条记本电脑的 ACPI 表都是为 通博8888 2001 设置的。

是的,你的 通博8888官网 零碎曾经预备好用于 通博8888 2001 了,你要思索装置吗?与设置装备摆设树差别,ACPI 具无方法和数据,而设置装备摆设树更多地是一种硬件描绘言语。ACPI 办法在启动后仍处于运动形态。比方,运转 acpi_listen 下令(在 apcid 包中),然后翻开和封闭条记本机盖会发明 ACPI 功用不断在运转。临时地和静态地 掩盖 ACPI 表 是能够的,而永世地改动它需求在引导时与 BIOS 菜单交互或革新 ROM。假如你遇到那么多费事,大概你应该 装置 coreboot,这是开源固件的替换品。

从 start_kernel() 到用户空间

init/main.c 中的代码居然是可读的,并且风趣的是,它依然在运用 1991 - 1992 年的 Linus Torvalds 的原始版权。在一个刚启动的零碎上运转 dmesg | head,其输入次要泉源于此文件。第一个 CPU 注册到零碎中,全局数据构造被初始化,而且调理顺序、中缀处置顺序(IRQ)、定时器和控制台依照严厉的次序逐一启动。在 timekeeping_init() 函数运转之前,一切的工夫戳都是零。内核初始化的这局部是同步的,也便是说实行只发作在一个线程中,在最初一个完成并前往之前,没有任何函数会被实行。因而,即便在两个零碎之间,dmesg 的输入也是完全可反复的,只需它们具有相反的设置装备摆设树或 ACPI 表。通博8888官网 的举动就像在 MCU 上运转的 RTOS(及时操纵零碎)一样,如 QNX 或 VxWorks。这种状况继续存在于函数 rest_init() 中,该函数在停止时由 start_kernel() 挪用。

晚期的内核启动流程。

晚期的内核启动流程。

函数 rest_init() 发生了一个新历程以运转 kernel_init(),并挪用了 do_initcalls()。用户可以经过将 initcall_debug 附加到内核下令行来监控 initcalls,如许每运转一次 initcall 函数就会发生 一个 dmesg 条款。initcalls 会历经七个延续的级别:early、core、postcore、arch、subsys、fs、device 和 late。initcalls 最为用户可见的局部是一切处置器核心设置装备摆设的探测和设置:总线、网络、存储和表现器等等,同时加载其内核模块。rest_init() 也会在引导处置器上发生第二个线程,它起首运转 cpu_idle(),然后等候调理器分派任务。

kernel_init() 也可以 设置对称多处置(SMP)构造。在较新的内核中,假如 dmesg 的输入中呈现 “Bringing up secondary CPUs...” 等字样,零碎便运用了 SMP。SMP 经过“热插拔” CPU 来停止,这意味着它用形态机来办理其生命周期,这种形态机在观点上相似于热插拔的 U 盘一样。内核的电源办理零碎常常会使某个core离线,然后依据需求将其叫醒,以便在不忙的呆板上重复挪用统一段的 CPU 热插拔代码。察看电源办理零碎挪用 CPU 热插拔代码的 BCC 东西 称为 offcputime.py

请留意,init/main.c 中的代码在 smp_init() 运转时简直已实行终了:引导处置器曾经完成了大局部一次性初始化操纵,别的核无需反复。虽然云云,跨 CPU 的线程依然要在每个核上天生,以办理每个核的中缀(IRQ)、任务行列步队、定时器和电源事情。比方,经过 ps -o psr 下令可以检查效劳每个 CPU 上的线程的 softirqs 和 workqueues。

  1. # ps -o pid,psr,comm $(pgrep ksoftirqd)
  2. PID PSR COMMAND
  3. 7 0 ksoftirqd/0
  4. 16 1 ksoftirqd/1
  5. 22 2 ksoftirqd/2
  6. 28 3 ksoftirqd/3
  7.  
  8. # ps -o pid,psr,comm $(pgrep kworker)
  9. PID PSR COMMAND
  10. 4 0 kworker/0:0H
  11. 18 1 kworker/1:0H
  12. 24 2 kworker/2:0H
  13. 30 3 kworker/3:0H
  14. [ . . . ]

此中,PSR 字段代表“处置器processor”。每个核还必需拥有本人的定时器和 cpuhp 热插拔处置顺序。

那么用户空间是怎样启动的呢?在最初,kernel_init() 寻觅可以代表它实行 init 历程的 initrd。假如没有找到,内核间接实行 init 自身。那么为什么需求 initrd 呢?

晚期的用户空间:谁规则要用 initrd?

除了设置装备摆设树之外,在启动时可以提供应内核的另一个文件途径是 initrd 的途径。initrd 通常位于 /boot 目次中,与 x86 零碎中的 bzImage 文件 vmlinuz 一样,或是与 ARM 零碎中的 uImage 和设置装备摆设树相反。用 initramfs-tools-core 软件包中的 lsinitramfs 东西可以列出 initrd 的内容。刊行版的 initrd 方案包括了最小化的 /bin/sbin/etc 目次以及内核模块,另有 /scripts 中的一些文件。一切这些看起来都很熟习,由于 initrd 大抵上是一个复杂的最小化 通博8888官网 根文件零碎。看似类似,实在否则,由于位于假造内存盘中的 /bin/sbin 目次下的一切可实行文件简直都是指向 BusyBox 二进制文件 的标记链接,由此招致 /bin/sbin 目次比 glibc 的小 10 倍。

假如要做的只是加载一些模块,然后在平凡的根文件零碎上启动 init,为什么还要创立一个 initrd 呢?想想一个加密的根文件零碎,解密能够依赖于加载一个位于根文件零碎 /lib/modules 的内核模块,固然另有 initrd 中的。加密模块能够被静态地编译到内核中,而不是从文件加载,但有多种缘由不盼望如许做。比方,用模块静态编译内核能够会使其太大而不克不及顺应存储空间,或许静态编译能够会违背软件答应条款。不出所料,存储、网络和人类输出设置装备摆设(HID)驱动顺序也能够存在于 initrd 中。initrd 根本上包括了任何挂载根文件零碎所必须的非内核代码。initrd 也是用户寄存 自界说ACPI 表代码的中央。

救济形式的 shell 和自界说的 initrd 照旧很故意思的。

救济形式的 shell 和自界说的 initrd 照旧很故意思的。

initrd 对测试文件零碎和数据存储设置装备摆设也很有效。将这些测试东西寄存在 initrd 中,并从内存中运转测试,而不是从被测工具中运转。

最初,当 init 开端运转时,零碎就启动啦!由于第二个处置器如今在运转,呆板曾经成为我们所熟知和喜欢的异步、可抢占、不行预测和高功能的生物。确实,ps -o pid,psr,comm -p 1 很容易表现用户空间的 init 历程已不在引导处置器上运转了。

总结

通博8888官网 引导进程听起来大概令人生畏,即便是复杂嵌入式设置装备摆设上的软件数目也是云云。但换个角度来看,启动进程相称复杂,由于启动中没有抢占、RCU 和竞争条件等虚无缥缈的庞大功用。只存眷内核和 PID 1 会疏忽了引导顺序和辅佐处置器为运转内核实行的少量预备任务。固然内核在 通博8888官网 顺序中是无独有偶的,但经过一些反省 ELF 文件的东西也可以理解其构造。学习一个正常的启动进程,可以协助运维职员处置启动的毛病。

【编辑引荐】

  1. 为初学者引见的通博8888官网 tee下令(6个例子)
  2. 为初学者复杂引见通博8888官网 ldd下令
  3. 通博8888官网容器平安的10个层面
  4. linux初级本领:效劳器集群之keepalived
  5. 功能剖析和调试东西:通博8888官网跟踪器之选
【责任编辑:庞桂玉 TEL:(010)68476606】

点赞 0
各人都在看
猜你喜好

读 书 +更多

Solaris 内核构造(第2版)

本书描绘了Solaris 10和OpenSolaris内核中一切次要子零碎的算法和数据构造,对第1版停止了大幅修订,参加了许多新的内容。全书从头至尾都采...

订阅51CTO邮刊

点击这里检查样刊

订阅51CTO邮刊