OpenWRT 启动流程(二) /etc/preinit 脚本分析

本系列导航:
OpenWRT 启动流程(一) /sbin/init 进程分析
OpenWRT 启动流程(二) /etc/preinit 脚本分析
OpenWRT 启动流程(三) /sbin/procd 分析

前面分析了 /sbin/init 最终是执行了 /etc/preinit 脚本
接着分析 /etc/preinit
同样是围绕下面两个问题:
1./etc/preinit 是怎么来的?
2./etc/preinit 做了些什么?

1./etc/preinit 是怎么来的?

它来自package/base-files/files/etc/preinit

2./etc/preinit 做了些什么?
#!/bin/sh
# Copyright (C) 2006-2016 OpenWrt.org
# Copyright (C) 2010 Vertical Communications

[ -z "$PREINIT" ] && exec /sbin/init

export PATH="/usr/sbin:/usr/bin:/sbin:/bin"

. /lib/functions.sh
. /lib/functions/preinit.sh
. /lib/functions/system.sh

boot_hook_init preinit_essential
boot_hook_init preinit_main
boot_hook_init failsafe
boot_hook_init initramfs
boot_hook_init preinit_mount_root

for pi_source_file in /lib/preinit/*; do
        . $pi_source_file
done

boot_run_hook preinit_essential

pi_mount_skip_next=false
pi_jffs2_mount_success=false
pi_failsafe_net_message=false

boot_run_hook preinit_main

先来看几个相关的函数定义,位于/lib/functions/preinit.sh
1.boot_hook_init
2.boot_hook_add
3.boot_hook_shift
4.boot_run_hook

1.boot_hook_init 的作用是初始化一个 name_hook变量
boot_hook_init() {
	local hook="${1}_hook"
	export -n "PI_STACK_LIST=${PI_STACK_LIST:+$PI_STACK_LIST }$hook"
	export -n "$hook="
}

例如:
执行 boot_hook_init preinit_main
环境变量中会有 preinit_main_book=未赋值

2.boot_hook_add 的作用是 将func 添加到 name_hook里
boot_hook_add() {
	local hook="${1}_hook${PI_HOOK_SPLICE:+_splice}"
	local func="${2}"

	[ -n "$func" ] && {
		local v; eval "v=\$$hook"
		export -n "$hook=${v:+$v }$func"
	}
}

例如:
执行
boot_hook_add preinit_main func1
boot_hook_add preinit_main func2
环境变量中会有 preinit_main_book=func1 func2

3.boot_hook_shift 作用是 从name_hook里取出一个值(从左至右)
boot_hook_shift() {
	local hook="${1}_hook"
	local rvar="${2}"

	local v; eval "v=\$$hook"
	[ -n "$v" ] && {
		local first="${v%% *}"  #取出第一个值

		[ "$v" != "${v#* }" ] && \
			export -n "$hook=${v#* }" || \   #删除第一个值
			export -n "$hook="

		export -n "$rvar=$first"
		return 0
	}

	return 1
}
4.boot_run_hook 的作用是逐个执行name_hook里的func 函数
boot_run_hook() {
	local hook="$1"
	local func

	while boot_hook_shift "$hook" func; do
		local ran; eval "ran=\$PI_RAN_$func"
		[ -n "$ran" ] || {
			export -n "PI_RAN_$func=1"
			$func "$1" "$2"
		}
	done
}

再回头看/etc/preinit

1.先是声明了五个book变量
boot_hook_init preinit_essential
boot_hook_init preinit_main
boot_hook_init failsafe
boot_hook_init initramfs
boot_hook_init preinit_mount_root
2.执行从/lib/preinit/* 里的脚本对preinit_main 等进行boot_hook_add
for pi_source_file in /lib/preinit/*; do
	. $pi_source_file
done

例如:/lib/preinit/02_default_set_state

define_default_set_state() {
	. /etc/diag.sh
}

boot_hook_add preinit_main define_default_set_state

将define_default_set_state函数追加到preinit_main_book中

3.执行preinit_essential preinit_main里的函数
boot_run_hook preinit_essential

pi_mount_skip_next=false
pi_jffs2_mount_success=false
pi_failsafe_net_message=false

boot_run_hook preinit_main

/lib/preinit/* 里定义的函数最终在这被调用执行。
那么/etc/preinit 做了些什么?具体就要看/lib/preinit/里的文件了。

/lib/preinit/
├── 00_preinit.conf
├── 02_default_set_state
├── 02_sysinfo
├── 03_b53_hack.sh
├── 10_indicate_failsafe
├── 10_indicate_preinit
├── 30_failsafe_wait
├── 40_run_failsafe_hook
├── 50_indicate_regular_preinit
├── 70_initramfs_test
├── 79_move_config
├── 80_mount_root
├── 81_urandom_seed
├── 99_10_failsafe_login
└── 99_10_run_init

你可能感兴趣的:(OpenWrt,/etc/preinit,openwrt,/etc/preinit)