openwrt是通過一系列shell腳本進行啟動流程的組織,下面是啟動流程的提綱。如
果想詳細了解啟動的過程,則需要仔細走讀腳本文件。
1. 在make menuconfig 選擇target平台 Atheros AP147
2. linux內核的配置文件由下面兩個文件組成
target/linux/ar71xx/config-3.3和根目錄下的.config中的內核配置部分組成
3. 在內核啟動時,我們會發現如下的啟動參數:
Kernel command line: board=AP147 console=ttyS0,115200 mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,6848k(rootfs),1472k(kernel),6144k(rootfs2),1472k(kernel2),64k(config),64k(art),16000k@0x50000(firmware) rootfstype=squashfs,jffs2 noinitrd
這一部分的參數,實際上是由patch-cmdline這個工具在image生成時patch到kernel中區的,詳細內容可以在內核目錄搜索CONFIG_IMAGE_CMDLINE_HACK宏
我們倒回來看,linux內核啟動后,首先查找root的啟動參數,如果沒有的話,首先運行/etc/preinit腳本,詳細見build_dir/linux-ar71xx_generic/linux-3.3.8/init/main.c 中的init_post函數
4. preinit腳本位置在
package/base-files/files/etc/preinit
5. preinit腳本是一系列腳本的入口,這一系列腳本放在下面的目錄:
package/base-files/files/lib/preinit
target/linux/ar71xx/base-files/lib/preinit
編譯完成后,會統一放在rootfs的/lib/preinit目錄下,
02_default_set_state
03_preinit_do_ar71xx.sh
05_enable_reset_button_ar71xx
05_mount_skip
05_set_iface_mac_ar71xx
05_set_preinit_iface_ar71xx
10_check_for_mtd
10_essential_fs
10_indicate_failsafe
10_indicate_preinit
20_check_jffs2_ready
20_device_fs_mount
30_device_fs_daemons
30_failsafe_wait
40_init_shm
40_mount_devpts
40_mount_jffs2
40_mount_ubifs
40_run_failsafe_hook
41_merge_overlay_hooks
50_choose_console
50_indicate_regular_preinit
60_init_hotplug
70_initramfs_test
70_pivot_jffs2_root
70_pivot_ubifs_root
80_mount_root
81_load_wifi_board_bin
90_init_console
90_mount_no_jffs2
90_restore_config
99_10_failsafe_login
99_10_mount_no_mtd
99_10_run_init
由於腳本眾多,因此openwrt的設計者將這些腳本分成下面幾類:
preinit_essential
preinit_main
failsafe
initramfs
preinit_mount_root
每一類函數按照腳本的開頭數字的順序運行。
6. preinit則執行下面的兩類腳本
boot_run_hook preinit_essential
boot_run_hook preinit_main
7. preinit執行的最后一個腳本為99_10_run_init,運行
exec env - PATH=$pi_init_path $pi_init_env $pi_init_cmd
pi_init_cmd為
pi_init_cmd="/sbin/init"
因此開始運行busybox的init命令
8. busybox的init命令執行inittab的腳本,該腳本來自
package/base-files/files/etc/inittab
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K stop
tts/0::askfirst:/bin/ash --login
ttyS0::askfirst:/bin/ash --login
tty1::askfirst:/bin/ash --login
sysinit為系統初始化運行的 /etc/init.d/rcS S boot腳本
shutdown為系統重啟或關機運行的腳本
tty開頭的是,如果用戶通過串口或者telnet登錄,則運行/bin/ash --login
askfirst和respawn相同,只是在運行前提示"Please press Enter to activate
this console."
9. 當前啟動轉到運行 /etc/init.d/rcS S boot,該腳本來自
package/base-files/files/etc/init.d/rcS
和preinit類似,rcS也是一系列腳本的入口,其運行/etc/rc.d目錄下S開頭的的所
有腳本(如果運行rcS K stop,則運行K開頭的所有腳本)
K10mcproxy
K50dropbear
K90network
K95luci_fixtime
K98boot
K99umount
S05defconfig
S05luci_fixtime
S10boot
S11ubus
S20network
S39usb
S45firewall
S50cron
S50dropbear
S50qos
S50radvd
S50telnet
S50uhttpd
S59luci_dhcp_migrate
S60dnsmasq
S60quagga
S95done
S95miniupnpd
S96led
S97watchdog
S98sysntpd
S99mcproxy
S99sysctl
上面的腳本文件來自:
package/base-files/files/etc/init.d
target/linux/ar71xx/base-files/etc/init.d
還有一些腳本來自各個模塊,在install時拷貝到rootfs,比如dropbear模塊
package/dropbear/files/dropbear.init
這些腳本先拷貝到/etc/init.d下,然后通過/etc/rc.common腳本,將init.d的腳
本鏈接到/etc/rc.d目錄下,並且根據 這些腳本中的START和STOP的關鍵字,添加
K${STOP}和S${START}的前綴,這樣就決定了腳本的先后的運行次序。
10.可以看出,openwrt的啟動主要是兩個階段,preinit主要是完成系統的初始化
(如文件系統的准備、模塊的加載),rcS主要依次 啟動各個模塊。