openwrt是一个开放的linux平台,主要用于带wifi的无线路由上。类似于ubuntu、red hat、之类的linux发行版本,它也有一套自己的启动流程。本文主要介绍了openwrt启动过程及详细分析。
1、概述
在linux的发展过程中,linux的启动程序也在发展,从sysv init到现在的upstart、systemd,通常该程序是进程号为1的进程,该程序在linux系统有着举足轻重的地方。在openwrt中,使用了另外一种启动程序叫做procd,本文的重点并不在于介绍procd,本文主要介绍并解析procd、preinit及各种脚本如何完成整个系统的初始化。
2、软件环境
linux发行版:ubuntu14.04 lts
openwrt版本:barrier break 14.07 r42635 (linux kernel 3.10.49)
硬件:mpr-a2模块(rt5350)
在查看linux内核代码及根文件系统下的脚本之前,需要对openwrt进行配置,运行make menuconfig,在target system中选择ralink rt288x/rt3xxx,subtarget中选择rt3x5x/rt5350based boards,target profile选择hame mpr-a2,然后make完成openwrt的编译。打完patch的内核代码在build_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/linux-ramips_rt305x/目录下,根文件系统目录在build_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/root-ramips/。
3、启动分析
3.1 内核启动点
linux的启动入口为start_kernel()(init/main.c),该函数的最后会调用rest_init()(init/main.c),该函数创建两个内核线程init和kthreadd之后,进入死循环,即所谓的0号进程。init线程执行kenrel_init()(init/main.c)函数,在kernel_init函数中,首先会检查内核的启动参数中是否有设置init参数,如果有,则会使用该参数指定的程序作为init程序,否则会按照如下代码(打上patch后的)中所示的顺序依次尝试启动,如果都无法启动就会导致kernel panic。
if (!run_init_process(“/etc/preinit”) ||
!run_init_process(“/sbin/init”) ||
!run_init_process(“/etc/init”) ||
!run_init_process(“/bin/init”) ||
!run_init_process(“/bin/sh”))
return 0;
在目前的环境下,内核启动参数未设置init参数,所以会以/etc/preinit程序作为init程序,preinit实际为shell脚本。
3.2 相关文件
3.2.1 脚本文件
/etc/preinit
/lib/functions.sh
/lib/functions/preinit.sh
/lib/functions/system.sh
/lib/preinit/下所有脚本
3.2.2 init程序
在proc程序包中,编译完会生成两个可执行程序:init和procd,均在目 录/sbin下,这两个程序均会使用到。
3.3 过程分析
这个初始化过程遵循如下主线:
下面我们一步一步分析这个过程。
在/etc/preinit脚本中,第一条命令如下:
[ -z “$preinit” ] && exec /sbin/init
在从内核执行这个脚本时,preinit这个变量时没有定义的,所以会直接执行/sbin/init。/sbin/init程序主要做了一些初始化工作,如环境变量设置、文件系统挂载、内核模块加载等,之后会创建两个进程,分别执行/etc/preinit和/sbin/procd,执行/etc/preinit之前会设置变量preinit,/sbin/procd会带-h的参数,当procd退出后会调用exec执行/sbin/proc替换当前init进程(具体过程可参见procd程序包中的init和procd程序)。这就是系统启动完成后,ps命令显示的进程号为1的进程名最终为/sbin/procd的由来,中间是有几次变化的。
继续看/etc/preinit脚本,出来变量设置外,接下来是执行了三个shell脚本:
/lib/functions.sh
/lib/functions/preinit.sh
/lib/functions/system.sh
注意“。”和“/”之间是有空格的,这里的点相当与souce命令,但souce是bash特有的,并不在posix标准中,“。”
是通用的用法。使用“。”的意思是在当前shell环境下运行,并不会在子shell中运行。这几个shell脚本主要定义了shell函数,
特别是preinit.sh中,定义了hook相关操作的函数。
之后会使用boot_hook_init定义五个hook结点如下:
boot_hook_init preinit_essential
boot_hook_init preinit_main
boot_hook_init failsafe
boot_hook_init initramfs
boot_hook_init preinit_mount_root
之后会向这些结点中添加hook函数。
在之后就是一个循环,依次在当前shell下执行/lib/preinit/目录下的脚本,
for pi_source_file in /lib/preinit/*; do
$pi_source_file
done
/lib/preinit/目录下的脚本具体类似的格式,定义要添加到hook结点的函数,然后通过boot_hook_add将该函数添加到对应的hook结点。
最后,/etc/preinit就会执行boot_run_hook函数执行对应hook结点上的函数。在当前环境下只执行了preinit_essential和
preinit_main结点上的函数,如下:
boot_run_hook preinit_essential
boot_run_hook preinit_main
到此,/etc/preinit执行完毕并退出。如果需要跟踪调试这些脚本,可以 在/etc/preinit的最开始添加一条命令set -x,这样就会打印出执行命令的过程, 当并不会真正执行。
至于系统服务程序的启动及初始化将全由procd完成,procd的功能不仅在于此,它还集成更多其他功能,具体可参见procd的资料。
智能锁将逐渐取代机械锁走进千家万户
PMP7499正激转换器参考设计
镍镉电池正负极反极物质
10月全球最畅销电动汽车榜单出炉五菱位居第二
为什么变压器的铁芯要进行冲片叠装
openwrt启动过程详细分析
三星增强现实新专利_可搭配车辆使用AR眼镜导航应用
传感器的7大感应方式介绍
复旦微自研存储芯片通过AEC-Q100 Grade 1车规级验证
基于正交频分复用技术的自动PLC/AMR方案
如何实现电平转换,多种方法
中一科技该如何实现净利润增长?
对于长安福特出的这款福特翼搏,如此的配置令你满意吗?
同轴电缆已被广泛应用于射频或音视频的传输
常见的运动控制器有哪些
差分探头的特点及用途有哪些
华为坚持物联网基础设施构建者、平台搭建者、联接创新者、生态推动者的定位
配电变压器损坏的原因分析及解决方法
高性能SiC JFET SJEP120R100A的操作和性能
华为平板M6曝光将有8.4英寸和10.1英寸两种版本均搭载了麒麟980处理器