1. 程式人生 > >OpenWrt啟動過程分析+新增自啟動指令碼

OpenWrt啟動過程分析+新增自啟動指令碼

http://blog.csdn.net/jk110333/article/details/39529459

總結一下OpenWrt的啟動流程:1.CFE->2.linux->3./etc/preinit->4./sbin/init ->5./etc/inittab ->6./etc/init.d/rcS->7./etc/rc.d/S* ->8.
 OpenWrt是一個開放的linux平臺,主要用於帶wifi的無線路由上。
類似於Ubuntu、Red Hat、之類的linux發行版本,它也有一套自己的啟動流程。下面,我就以我的Linksys 的WRT54G為平臺介紹一下,OpenWrt的啟動流程。



      1.首先,CFE(common firmware environment)--它就是一個bootloader,類似u-boot,redboot之類,有點broadcom公司御用之嫌--
最先啟動。它的任務只是創造一個簡單的環境,讓系統先執行起來。除了能夠跳轉到特定地址上啟動作業系統(如Linux)外,
它還能讓你download東西到上面,比如download一個linux,然後啟動它。
另外,值得一提的是,CFE在啟動之後會有1,2秒的時間等待由tftp上傳的核心並燒寫到flash上,

這就給一些作業系統損壞但CFE還能工作的"磚頭"板一個起死回生的機會。請注意一旦linux啟動之後,將由linux全部接管系統,


       2.這時候就沒CFE什麼事情了。唯一的瓜葛是CFE傳遞給核心一個命令列的引數,這個可以在linux啟動起來之後用下面的命令檢視:

[email protected]:/# cat /proc/cmdline
console=ttyS0,115200 mtdparts=spi_flash:1m(u-boot)ro,3m(kernel),-(rootfs)

之後,linux系統啟動起來了。它使用類似如下的指令碼命令來解析cmdline:

for x in $(cat /proc/cmdline); do
case $x in
init=*)
init=${x#init=}
;;
root=*)
ROOT=${x#root=}

case $ROOT in
LABEL=*)
ROOT="/dev/disk/by-label/${ROOT#LABEL=}"
;;
UUID=*)
ROOT="/dev/disk/by-uuid/${ROOT#UUID=}"
;;
esac
;;
rootflags=*)
ROOTFLAGS="-o ${x#rootflags=}"
;;
cryptopts=*)
cryptopts="${x#cryptopts=}"
;;
nfsroot=*)
NFSROOT="${x#nfsroot=}"
;;
nfsopts=*)
NFSOPTS="-o ${x#nfsopts=}"
;;
boot=*)
BOOT=${x#boot=}
;;
resume=*)
RESUME=${x#resume=}
;;
noresume)
NORESUME=y
;;
quiet)
quiet=y
;;
ro)
readonly=y
;
rw)
readonly=0
;;
debug)
debug=y
exec >/tmp/initramfs.debug 2>&1
set -x
;;
break=*)
break=${x#break=}
;;
break)
break=premoun
;;
esac
done

對於OpenWrt這個cmdline的意思就是:root=/dev/mtdblock2 檔案系統在第三個flash分割槽上(mtdblock0,1,2);
rootfstype=squashfs,jffs2 檔案系統型別是squashfs和jffs2(為什麼兩種型別,目前還不清楚,
不過可以確定OpenWrt使用了較為複雜的檔案系統,實現了squashfs的壓縮和jffs2的可寫 ); 

init=/etc/preinit 執行該初始化,noinitrd console=ttyS0,115200

沒有initrd和console口設定。

   3.
init=/etc/preinit 是linux會執行的初始化,具體內容如下:
[email protected]:/# cat /etc/preinit

#!/bin/sh
# Copyright (C) 2006 OpenWrt.org
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
. /etc/diag.sh
failsafe_ip() {

ifconfig $ifname 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.2 55 up

}

failsafe() {

[ -n "$ifname" ] && grep "$ifname" /proc/net/dev >/dev/null && {

failsafe_ip
netmsg 192.168.1.255 "Entering Failsafe!"
telnetd -l /bin/login <> /dev/null 2>&1
}

lock /tmp/.failsafe
ash --login

}
mount proc /proc -t proc
mount sysfs /sys -t sysfs
size=$(awk '/MemTotal:/ {l=5242880;mt=($2*1024);print((s=mt/2)<l)&&(mt>l)?mt-l:s }' /proc/meminfo)
mount tmpfs /tmp -t tmpfs -o size=$size,nosuid,nodev,mode=1777

if grep devfs /proc/filesystems > /dev/null; then
mount devfs /dev -t devfs

M0=/dev/pty/m0

M1=/dev/pty/m1

HOTPLUG=/sbin/hotplug-call
elif [ -x /sbin/hotplug2 ]; then
mount -t tmpfs tmpfs /dev -o size=512K
mknod /dev/console c 5 1
/sbin/hotplug2 --coldplug --set-rules-file /etc/hotplug2-init.rules
/sbin/hotplug2 --no-coldplug --persistent --set-rules-file /etc/hotplug2 -init.rules &
M0=/dev/ptmx
M1=/dev/ptmx
HOTPLUG=
elif [ -x /sbin/udevd ]; then
mount -n -t tmpfs -o mode=0755 udev /dev
/sbin/uevd --daemon
/sbin/udevtrigger
/sbin/udevsettle
M0=/dev/pty/ptmx
M1=/dev/pty/ptmx
HOTPLUG=
fi
mkdir -p /dev/pts /dev/shm
mount devpts /dev/pts -t devpts

# the shell really doesn't like having stdin/out close

# that's why we use /dev/pty/m0 and m1 as replacement

# for /dev/console if there's no serial console available

dd if=/dev/console of=/dev/null bs=1 count=0 >/dev/null 2>/dev/null && {
M0=/dev/console
M1=/dev/console
}
exec <$M0 >$M1 2>&0
echo "- preinit -"

echo "Press CTRL-C for failsafe"

trap 'FAILSAFE=true' INT

trap 'FAILSAFE=true' USR1


[ -e /etc/preinit.arch ] && . /etc/preinit.arch


set_state preinit


echo "$HOTPLUG" > /proc/sys/kernel/hotplug


eval ${FAILSAFE:+failsafe}


lock -w /tmp/.failsafe
if [ -z "$INITRAMFS" ]; then
    mount_root
[ -f /sysupgrade.tgz ] && {
    echo "- config restore -"
    cd /
    mv sysupgrade.tgz /tmp
    tar xzf /tmp/sysupgrade.tgz
    rm -f /tmp/sysupgrade.tgz
   sync
}
echo "- init -"
exec /sbin/init
fi

可見,它主要是掛載一些系統需要的檔案系統,例如tmpfs,proc和sysfs(是否真正掛載取決於核心是否2.6的)。

並且會準備裝置節點和故障恢復(failsafe)的準備。(這裡還沒看懂 )
       4.
最後,exec /sbin/init啟動檔案系統,在OpenWrt上也就是busybox的init程式。

它會自動分析/etc/inittab這個檔案,其內容解釋詳見busybox網站的cmd help。

 5.


/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
     6.

執行/etc/init.d/rcS:

#!/bin/sh
# Copyright (C) 2006 OpenWrt.org
run_scripts() {
for i in /etc/rc.d/$1*; do
[ -x $i ] && $i $2 2>&1
done | $LOGGER

}

LOGGER="cat"
[ -x /usr/bin/logger ] && LOGGER="logger -s -p 6 -t sysinit"
if [ "$1" = "S" ]; then
run_scripts "$1" "$2" &

else

run_scripts "$1" "$2"

fi

    7.

將執行/etc/rc.d/S*這些指令碼: 
[email protected]:/# ls /etc/rc.d/S*
/etc/rc.d/S10boot 
/etc/rc.d/S50cron 
/etc/rc.d/S60led
/etc/rc.d/S20fstab 
/etc/rc.d/S50dropbear 
/etc/rc.d/S95done
/etc/rc.d/S39usb 
/etc/rc.d/S50uhttpd 
/etc/rc.d/S97watchdog
/etc/rc.d/S40network 
/etc/rc.d/S50telnet 
/etc/rc.d/S99sysctl
/etc/rc.d/S45firewall /
etc/rc.d/S60dnsmasq
按照數字從小到大的順序執行。


二、實現自啟動指令碼

OpenWRT的啟動指令碼放在 /etc/init.d 目錄下,而系統開機時自動執行/etc/rc.d目錄下的指令碼。所以在rc.d目錄下、有init.d下指令碼的連結檔案。
整理一下

05 defconfig //載入預設引數
10 boot //啟動
39 usb // 載入usbfs
40 network // 設定網絡卡引數
45 firewall // 防火牆
50 dropbear // sshd server
50 cron // .....
50 telnet // 如果沒有修改root密碼,則啟動telnet server
60 dnsmasq // DHCP 和 DNS 服務端
95 done // ..
96 led // 指示燈
97 watchdog // ...
99 sysctl // 最後,進行必要的核心引數調整

然後,我們加入自己的指令碼,實現模組驅動的載入、應用程式的開機自啟動等。

首先在/etc/init.d裡新增需要啟動的shell指令碼

例如:
vim startCamera
內容:

 #!/bin/sh /etc/rc.common
 # /init.d/startCamera
START=50
start()
{
     ./opt/ipnc/system_server &
}

stop()
{
    killallsystem_server
}
之後還需要在rc.d目錄下做一個連結,啟動時系統會按順序啟動rc.d目錄下的指令碼連結,對應執行init.d目錄下的啟動指令碼。指令碼的命名要符合系統規範,init.d下telnet指令碼在rc.d目錄下的連結檔名為S50telnet。所以連結檔案要在指令碼名前加S+啟動順序數字,啟動順序要等系統進行完必要的初始化。所以我們命名為S95+指令碼名。


命令:ln -s /etc/init.d/startCamera /etc/rc.d/S95startCamera


重啟,即可


現在實現了應用程式的開機自啟動。

相關推薦

OpenWrt啟動過程分析+新增啟動指令碼[轉載]

一、OpenWrt啟動過程分析 總結一下OpenWrt的啟動流程:1.CFE->2.linux->3./etc/preinit->4./sbin/init ->5./etc/inittab ->6./etc/init.d/rcS->7./etc/rc.d/S*

OpenWrt啟動過程分析+新增啟動指令碼

http://blog.csdn.net/jk110333/article/details/39529459 總結一下OpenWrt的啟動流程:1.CFE->2.linux->3./etc/preinit->4./sbin/init ->5./et

OpenWrt啟動過程分析+新增啟動指令碼########33 openwrt blog

####################### http://blog.chinaunix.net/uid/26675482/cid-200203-list-1.html       ------###33  openwrt   blog ##############

ubuntu開機啟動svn(新增啟動

1. 問題描述    今天伺服器重啟了之後,在手動啟動svn服務的時候,想寫個指令碼,讓ubuntu的開機自啟動svn服務。2. 解決方法    2.1 寫個指令碼startsvn.sh        #!/bin/bash        svnserve -d -r /ho

OpenWrt啟動過程分析

總結一下OpenWrt的啟動流程:1.CFE->2.linux->3./etc/preinit->4./sbin/init ->5./etc/inittab ->6./etc/init.d/rcS->7./etc/rc.d/S* -&g

Linux下新增定義指令碼到開機啟動的方法

chkconfig --add auto_coreseek.sh   完事。   然後研究下這都是些毛意思。 chkconfig有幾個等級: 0:表示關機 1:表示單使用者模式 2:表示無網路連結多使用者命令列模式 3:表示有網路連結多使用者命令列模式 4:表示不可用情況 5:表示帶圖形介面的多使用者模式 6

【轉】Android 4.0 Launcher2源碼分析——啟動過程分析

handler flag 這一 第一次啟動 asynctask pla size ontouch wait Android的應用程序的入口定義在AndroidManifest.xml文件中可以找出:[html] <manifest xmlns:android="htt

X86架構下Linux啟動過程分析

重要 ack csdn 檢查 point article span 註意 eap 1、X86架構下的從開機到Start_kernel啟動的整體過程 這個過程簡要概述為: 開機——>BIOS——>GRUB/LILO——>Linux Kernel

Linux開機啟動過程分析

物理內存 登錄 page thread 陷阱門 execute 啟動過程 font 定義 Linux開機啟動過程分析 開機過程指的是從打開計算機電源直到LINUX顯示用戶登錄畫面的全過程。分析LINUX開機過程也是深入了解LINUX核心工作原理的一個很好的途徑。 啟動第一

u-boot-201611 啟動過程分析——基於smdk2410

u-bootu-boot-201611 啟動過程分析——基於smdk2410

linux 系統啟動過程分析

系統root 密碼丟失故障 linux啟動順序主板BIOS加電自檢 檢查硬件--> 讀取硬盤引導扇區(MBR)--> 啟動引導程序(grub)--> 選擇系統--> 加載系統內核(kernel shell)--> 啟動系統讀取相應的默認設置(環境變量,運行級別)--

Ocata Neutron代碼分析(一)——Neutron API啟動過程分析

process fig ddr arch 異常 run tap 文件中 bridge 首先,Neutron Server作為一種服務(neutron-server.service),可以到Neutron項目目錄中的setup.cfg配置文件中找到對應的代碼入口。 [ent

Ocata Neutron代碼分析(二)——Neutron RPC啟動過程分析

gre add ice common multi tween wait函數 tex 依次 RPC啟動跟Neutron API的啟動在同一個函數中執行,neutron.server.wsgi_eventlet.py中的eventlet_wsgi_server。 def ev

Linux進程啟動過程分析do_execve(可執行程序的加載和運行)---Linux進程的管理與調度(十一)

[] flag 表示 conn nali 最終 roc 不同的 recursion execve系統調用 execve系統調用 我們前面提到了, fork, vfork等復制出來的進程是父進程的一個副本, 那麽如何我們想加載新的程序, 可以通過execve來加載和啟動新的程

OpenWRT新增指令碼

OpenWRT的啟動指令碼放在 /etc/init.d 目錄下,而系統開機時自動執行/etc/rc.d目錄下的指令碼。所以在rc.d目錄下、有init.d下指令碼的連結檔案。原始碼中init.d位置在:/package/base-files/files/etc/init.d vi p

AliOS Things的啟動過程分析(二)

AliOS Things的啟動過程分析(二) 在AliOS Things的啟動過程分析(一)中分析了developerkit從系統上電到呼叫main函式所經歷的一些步驟,接下來詳細分析一下main函式的一些工作,主要是核心的相關初始化工作。main函式所處的位置位於    

OSAL啟動過程分析

一、SimpleBLEBroadcaster  OSAL啟動過程分析: Main() ==> HAL_BOARD_INIT();//初始化硬體 ==> InitBoard( OB_COLD );//初始化板卡IO ==> HalDriverInit();

STM32之啟動過程分析學習筆記

 System memory內建了ST提供的boot loader,可以通過該boot loader下載程式到Flash中。 使用者程式實際只能儲存在Flash中,且能在Flash和SRAM中執行(因為cortex-m3核採用哈佛結構,程式

《16.核心的啟動過程分析

《16.核心的啟動過程分析》 第一部分、章節目錄 2.16.1.做好核心分析的準備工作 2.16.2.head.S檔案分析1 2.16.3.核心啟動的彙編階段 2.16.4.核心啟動的C語言階段1 2.16.5.核心啟動的C語言階段2 2.16.6.核心啟動的C語言階段3 2.16.7.

Linux啟動過程分析(十一)---da850_set_emif_clk_rate()函式分析

/* * 雖然在bootloader中已經把emif的時鐘速率設定為允許的值,但是核心需要重新 *設定以使它支援平臺請求的特定時鐘速率。 */ ret = da850_set_emif_clk_rate()-> static __init int da850_set_emif_c