/etc/init.d/rcS內容分析

2012-11-29 18:40

/etc/init.d/rcS內容分析

/etc/init.d/rcS內容分析

        由於init=/linuxrc,因此,在文件系統掛載後,運行的第一個程序就是根目錄下的linuxrc,而這是一個指向/bin/busybox 的鏈接,也就是說,系統起來後運行的第一個程序就是busybox本身。                 

        busybox首先將試圖解析/etc/inittab來獲取進一步的初始化配置信息(參考busybox源代碼init/init.c中的parse_inittab()函數)。而事實上,root_qtopia中並沒有/etc/inittab這個配置文件,根據busybox的裸機,它將生成默認的配置。其中最重要的一個,就是new_init_action(SYSINIT,INIT_SCRIPT,""),也就決定了接下來初始化的腳本是INIT_SCRIPT所定義的值,這個宏的默認值是"etc/init.d/rcS"。

        下面是文件系統中/etc/init.d/rcS的內容,也是我們要分析的重點

1.PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:

2.runlevel=S

3.prevlevel=N

4.umask 022

5.export PATH runlevel prevlevel

##爲啓動環境設置必要的環境變量;

1./bin/hostname FriendlyARM

##設置機器名字;

1./bin/mount -n -t proc none /proc

2./bin/mount -n -t sysfs none /sys

3./bin/mount -n -t usbfs none /proc/bus/usb

4./bin/mount -t ramfs none /dev

##掛載"虛擬"文件系統"/proc"和"/sys",並且在/dev目錄下掛載一個ramfs,相當於把原本nandflash上的只讀的/dev目錄"覆蓋"上一塊可寫的空的SDRAM。

##這裏要注意的是,/sys和掛載了ramfs的/dev是正確創建設備節點的關鍵。對於2.6.29內核來說,已經沒有devfs的支持,創建設備節點只有通過兩種辦法由文件系統完成:

1)製作文件系統鏡像前用mknod手動創建好系統所有的(包括可能有的)設備節點,並把這些節點文件一起做進文件系統鏡像中;

2)在文件系統初始化過程中,通過/sys目錄所輸出的信息,在/dev目錄下動態的創建系統中當前實際有的設備節點。

        顯然,方法1)有很大的侷限性,僅限於沒有設備動態增加或減少的情況,不適用於很多設備熱插拔的情況,比如U盤,SD卡等等。方法2)是目前大多數PC上的linux的做法(基於udev實現)。這種方法有2個前提:/sys目錄掛載和一個可寫的/dev目錄。這也就是爲什麼我們這裏需要掛載/sys和ramfs在/dev目錄上,事實上,這種方法最早就是爲熱插拔設計的,你可以理解爲當系統啓動時,所有設備一下子全部"插入"了進來。

        這裏有一點要說明的是,在文件系統初始化跑到這裏之前,原來的/dev目錄下必須有一個設備節點:/dev/console。

        其實,要搞清楚"程序"這種東西,沒有什麼好的辦法,無非2個東西,源碼和腳本

1.echo /sbin/mdev> /proc/sys/kernel/hotplug

2./sbin/mdev -s

3./bin/hotplug

##這幾個就是用來完成上面所說的兩個東西:1)通過mdev -s在/dev目錄下創建必要的設備節點;2)設置內核的hotplug handler 爲mdev,即當設備熱插拔時,由mdev接受來自內核的消息並作出相應的迴應,比如掛載U盤。

        對於mdev,需要注意的是,文件系統裏存在/etc/mdev.conf文件,它包含了medv的配置信息。通過這個文件,我們可以自定義一些設備節點的名稱或鏈接來滿足特定的需要。這是root qtopia中mdev.conf的內容:

1.#system all-writable devices

2.full 0:0 0666

3.null 0:0 0666

4.ptmx 0:0 0666

5.random 0:0 0666

6.tty 0:0 0666

7.zero 0:0 0666

8.

9.#console devices

10.tty[0-9]* 0:5 0660

11vc/[0-9]* 0:5 0660

12.     
13.   # serial port devices   
14.   s3c2410_serial0    0:5    0666    =ttySAC0   
15.   s3c2410_serial1    0:5    0666    =ttySAC1   
16.   s3c2410_serial2    0:5    0666    =ttySAC2   
17.   s3c2410_serial3    0:5    0666    =ttySAC3   
18.                                                                                                                                                          19.   # loop devices   
20.   loop[0-9]*    0:0    0660    =loop/   
21.     
22.   # i2c devices   
23.   i2c-0        0:0    0666    =i2c/0   
24.   i2c-1        0:0    0666    =i2c/1   
25.     
26.   # frame buffer devices   
27.   fb[0-9]        0:0    0666   
28.     
29.   # input devices   
30.   mice        0:0    0660    =input/   
31.   mouse.*        0:0    0660    =input/   
32.   event.*        0:0    0660    =input/   
33.   ts.*        0:0    0660    =input/   
34.     
35.   # rtc devices   
36.   rtc0        0:0    0644    >rtc   
37.   rtc[1-9]    0:0    0644   
38.     
39.   # misc devices    

40.   mmcblk0p1    0:0    0600    =sdcard */bin/hotplug   
41.   sda1        0:0    0600    =udisk * /bin/hotplug

可以看到,原本串口驅動註冊的設備名是 s3c2410_serial0, s3c2410_serial1 和
s3c2410_serial2,而 mdev 則會在/dev 目錄下對應生成 ttySAC0, ttySAC1和ttySAC2以符合
應用程序對於串口設備名稱的習慣。同樣的,/dev/sdcard和/dev/udisk 永遠分別指向 SD 卡和
U盤的第一個分區。(所以,用那些沒有分區表的SD卡或U盤的兄弟知道原因了吧...)

1.#mounting file system specified in /etc/fstab

2.mkdir -p /dev/pts

3.mkdir -p /dev/shm

4./bin/mount -n -t devpts none /dev/pts -o mode=0622

5.     /bin/mount -n -t tmpfs tmpfs /dev/shm   
6.     /bin/mount -n -t ramfs none /tmp   
7.     /bin/mount -n -t ramfs none /var

8.mkdir -p /var/empty

9.mkdir -p /var/log

10.mkdir -p/var/lock

11.mkdir -p/var/run

12.mkdir -p /var/tmp

就像註釋中所說的,這是用來掛載其他一些常用的文件系統,並在/var 目錄下(同樣是
ramfs,可寫的)新建必要的目錄。 

1.     /sbin/hwclock -s 

用來設定系統時間的,從硬件 RTC 中獲取,要獲取正確的時間,必須先設置好正確的
時間(如何設置 RTC 見用戶手冊說明),目前友善之臂的開發板出廠時並沒有設置實際的時
間,而是系統默認的。

接下來就是啓動系統服務了,包括log記錄,網絡, http server和自定義的"跑馬燈服
務"... 
1.     syslogd   
2.     /etc/rc.d/init.d/netd start   
3.     echo "                        " > /dev/tty1                                                                                                      4.     echo "Starting networking..." > /dev/tty1   
5.     sleep 1   
6.     /etc/rc.d/init.d/httpd start   
7.     echo "                        " > /dev/tty1   
8.     echo "Starting web server..." > /dev/tty1   
9.     sleep 1   
10.   /etc/rc.d/init.d/leds start   
11.   echo "                        " > /dev/tty1   
12.   echo "Starting leds service..." > /dev/tty1   
13.   echo "                        "   
14.   sleep 1

啓動一系列服務: 
syslog - 用於記錄內核和應用程序 debug 信息 
netd -      inetd, 一個掛載啓動各種網絡相關服務的看守進程 
httpd -    http server看守進程 
leds -   跑馬燈看守進程 
其中,inetd的配置文件爲/etc/inetd.conf,這是文件內容 
1.     # /etc/inetd.conf: see inetd(8) for further informations.   
2.     echo      stream tcp    nowait    root    internal   
3.     echo      dgram    udp    wait    root    internal    

4.     daytime stream tcp    nowait    root    internal   
5.     daytime dgram    udp    wait    root    internal   
6.     time      stream tcp    nowait    root    internal   
7.     time      dgram    udp    wait    root    internal   
8.       
9.     # These are standard services.   
10. # 
11.   ftp    stream    tcp    nowait    root    /usr/sbin/ftpd        /usr/sbin/ftpd   
12.   telnet    stream    tcp    nowait    root    /usr/sbin/telnetd    /usr/sbin/telnetd -i

可以看到,這裏啓動的網絡服務有兩個: 1)ftp server 和 2)telnet server。有關網絡
服務的端口和協議等具體信息,可以參考/etc/services, /etc/protocols

1.     /sbin/ifconfig lo 127.0.0.1   
2.     /etc/init.d/ifconfig-eth0

配置網絡設備(網卡): 
1)設定本機迴環地址爲 127.0.0.1 
2)運行網卡設置腳本/etc/init.d/ifconfig-eth0 
這是/etc/init.d/ifconfig-eth0的內容, 加入了我的一些註釋 
複製代碼 
1.     #!/bin/sh    

2.       
3.     echo -n Try to bring eth0 interface up......>/dev/ttySAC0   
4.       
5.     #判斷/etc/eth0-setting文件是否存在 
6.     if [ -f /etc/eth0-setting ] ; then   
7.                           #讀取配置文件信息 
8.         source /etc/eth0-setting   
9.       
10.                         #如果根文件系統爲nfs,則說明網卡已經配置OK,這裏什麼都不需要配置了 
11.       if grep -q "^/dev/root / nfs " /etc/mtab ; then   
12.           echo -n NFS root ... > /dev/ttySAC0   
13.                         #否則,根據配置文件中的MAC, IP, Mask和Gateway通過ifconfig 命令相應地配置網卡 
14.       else   
15.           ifconfig eth0 down   
16.           ifconfig eth0 hw ether $MAC   
17.           ifconfig eth0 $IP netmask $Mask up   
18.           route add default gw $Gateway   
19.       fi   
20.     
21.                         #將配置文件中的DNS設置寫入/etc/resolv.conf 使之生效 
22.       echo nameserver $DNS > /etc/resolv.conf    

23.   #配置文件不存在,使用默認配置 
24. else 
25.                            
26.                         #如果根文件系統爲nfs,則說明網卡已經配置OK,這裏什麼都不需要配置了 
27.       if grep -q "^/dev/root / nfs " /etc/mtab ; then   
28.           echo -n NFS root ... > /dev/ttySAC0   
29.       else   
30.                         #將網卡的IP地址設定爲192.168.1.230 
31.       /sbin/ifconfig eth0 192.168.1.230 netmask 255.255.255.0 up   
32.       fi   
33. fi 
34.     
35.   echo Done > /dev/ttySAC0 
可以看到,NFS自動識別就是靠判斷/etc/mtab中是否有 nfs的掛載記錄實現的。 
這是 root qtopia文件系統中/etc/eth0-settings 文件

這是 root qtopia文件系統中/etc/eth0-settings 文件 
複製代碼 
1.     IP=192.168.1.230   
2.     Mask=255.255.255.0   
3.     Gateway=192.168.1.1   
4.     DNS=192.168.1.1   
5.     MAC=08:90:90:90:90:90

終於到最後了,啓動Qtopia GUI 環境 
複製代碼 
1.     /bin/qtopia &   
2.     echo "                                  " > /dev/tty1   
3.     echo "Starting Qtopia, please waiting..." > /dev/tty1

可以看到,這裏 Qtopia 是通過運行/bin/qtopia 來啓動的。事實上,/bin/qtopia 也是一
個腳本,它的任務是設定 Qtopia 運行必要的環境, 最後通過調用 qpe 可執行文件真正啓動
Qtopia。這是它的全部內容,我加入了一些註釋:

1.     #!/bin/sh 

2.
3. #tslib 環境變量設置,包括了touchscreen 設備文件,tslib 配置文件,tslib plug-in 位置和touchscreen 校準數據文件

4. export TSLIB_TSDEVICE=/dev/input/event0
5. export TSLIB_CONFFILE=/usr/local/etc/ts.conf
6. export TSLIB_PLUGINDIR=/usr/local/lib/ts
7. export TSLIB_CALIBFILE=/etc/pointercal

8. #Qtopia 環境變量設置,設定了Qtopia 主要文件位置
9. export QTDIR=/opt/Qtopia
10. export QPEDIR=/opt/Qtopia

11. #設定PATH 和LD_LIBRARY_PATH 以包含Qtopia 的可執行文件和共享庫文件,方便Qtopia 正確運行
12. export PATH=$QTDIR/bin:$PATH
13. export LD_LIBRARY_PATH=$QTDIR/lib:/usr/local/lib:$LD_LIBRARY_PATH
14.

15. #通過判斷/sys/devices/virtual/input/input0/uevent 中是否包含touchscreen 信息使Qtopia 自動識別touchscreen
和USB 鼠標
16. TS_INFO_FILE=/sys/devices/virtual/input/input0/uevent
17. if [ -e $TS_INFO_FILE -a "/bin/grep -q TouchScreen < $TS_INFO_FILE" ]; then
18. export QWS_MOUSE_PROTO="TPanel:/dev/input/event0 USB:/dev/input/mice"
19. if [ -e /etc/pointercal -a ! -s /etc/pointercal ] ; then
20. rm /etc/pointercal
21. fi
22. else
23. export QWS_MOUSE_PROTO="USB:/dev/input/mice"
24. >/etc/pointercal
25. fi
26. unset TS_INFO_FILE

27.
28. export QWS_KEYBOARD=TTY:/dev/tty1
29. export KDEDIR=/opt/kde
30.
31. export HOME=/root
32.
33. #通過調用/opt/Qtopia/bin/qpe 真正啓動Qtopia
34. exec $QPEDIR/bin/qpe 1>/dev/null 2>/dev/null

到此爲止,文件系統從初始化到最終啓動Qtopia GUI 環境的全部過程就結束了,大家
可以看到,友善之臂的“小祕密”其實都在這裏,說穿了很簡單:)只要大家能夠靜下心來認真看
看腳本,看看源代碼,加上一些背景知識的瞭解,搞清楚一個嵌入式系統就這麼簡單

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章