新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > MINI2440啟動配置文件/etc/init.d/rcS文件分析

        MINI2440啟動配置文件/etc/init.d/rcS文件分析

        作者: 時間:2016-11-10 來源:網絡 收藏
        Mini2440啟動配置文件說明
        對于mini2440,雖然root_qtopia這個文件系統的GUI是基于Qtopia的,但其初始化啟動過程卻是由大部分由busybox完成,Qtopia(qpe)只是在啟動的最后階段被開啟。
        由于默認的內核命令行上有init=/linuxrc, 因此,在文件系統被掛載后,運行的第一個程序是根目錄下的linuxrc。這是一個指向/bin/busybox的鏈接,也就是說,系統起來后運行的第一個程序也就是busybox本身。這種情況下,busybox首先將試圖解析/etc/inittab來獲取進一步的初始化配置信息(參考busybox源代碼init/init.c中的parse_inittab()函數)。而事實上,root_qtopia中并沒有/etc/inittab這個配置文件,根據busybox的邏輯,它將生成默認的配置(部分):
        static void parse_inittab(void)
        {
        #if ENABLE_FEATURE_USE_INITTAB
        char *token[4];
        parser_t *parser = config_open2("/etc/inittab", fopen_for_read);

        if (parser == NULL)
        #endif
        {
        /* No inittab file - set up some default behavior */
        /* Reboot on Ctrl-Alt-Del */
        new_init_action(CTRLALTDEL, "reboot", "");
        /* Umount all filesystems on halt/reboot */
        new_init_action(SHUTDOWN, "umount -a -r", "");
        /* Swapoff on halt/reboot */
        if (ENABLE_SWAPONOFF)
        new_init_action(SHUTDOWN, "swapoff -a", "");
        /* Prepare to restart init when a QUIT is received */
        new_init_action(RESTART, "init", "");
        /* Askfirst shell on tty1-4 */
        new_init_action(ASKFIRST, bb_default_login_shell, "");
        //TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
        new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
        new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
        new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
        /* sysinit */
        new_init_action(SYSINIT, INIT_SCRIPT, "");
        return;
        }
        ……
        其中, 最重要的一個,就是new_init_action(SYSINIT, INIT_SCRIPT, ""), 也就決定了接下去初始化的腳本是INIT_SCRIPT所定義的值。這個宏的默認值是"/etc/init.d/rcS"。
        下面是文件系統中/etc/init.d/rcS的內容, 也是我們要分析的重點

        #! /bin/sh

        PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
        runlevel=S
        prevlevel=N
        umask 022
        export PATH runlevel prevlevel

        #
        # Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
        #
        trap ":" INT QUIT TSTP
        /bin/hostname FriendlyARM

        /bin/mount -n -t proc none /proc
        /bin/mount -n -t sysfs none /sys
        /bin/mount -n -t usbfs none /proc/bus/usb
        /bin/mount -t ramfs none /dev

        echo /sbin/mdev > /proc/sys/kernel/hotplug
        /sbin/mdev -s
        /bin/hotplug

        # mounting file system specified in /etc/fstab
        mkdir -p /dev/pts
        mkdir -p /dev/shm
        /bin/mount -n -t devpts none /dev/pts -o mode=0622
        /bin/mount -n -t tmpfs tmpfs /dev/shm
        /bin/mount -n -t ramfs none /tmp
        /bin/mount -n -t ramfs none /var
        mkdir -p /var/empty
        mkdir -p /var/log
        mkdir -p /var/lock
        mkdir -p /var/run
        mkdir -p /var/tmp

        /sbin/hwclock -s

        syslogd
        /etc/rc.d/init.d/netd start
        echo " " > /dev/tty1
        echo "Starting networking..." > /dev/tty1
        sleep 1
        /etc/rc.d/init.d/httpd start
        echo " " > /dev/tty1
        echo "Starting web server..." > /dev/tty1
        sleep 1
        /etc/rc.d/init.d/leds start
        echo " " > /dev/tty1
        echo "Starting leds service..." > /dev/tty1
        echo " "
        sleep 1

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

        /bin/qtopia &
        echo " " > /dev/tty1
        echo "Starting Qtopia, please waiting..." > /dev/tty1
        下面就逐個來分析:
        1. 啟動環境設置必要的環境變量;
        PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin: runlevel=S prevlevel=N umask 022 export PATH runlevel prevlevel
        2. 設置機器名字;
        /bin/hostname FriendlyARM
        3. 掛載“虛擬”文件系統,
        /bin/mount -n -t proc none /proc
        /bin/mount -n -t sysfs none /sys
        /bin/mount -n -t usbfs none /proc/bus/usb
        /bin/mount -t ramfs none /dev
        這里是掛載/proc, /sys,并且在/dev目錄上掛載一個ramfs,相當于把原本NAND Flash上的只讀的/dev目錄“覆蓋”上一塊可寫的空的SDRAM。
        這里要注意的是,/sys和掛載了ramfs的/dev是正確創建設備節點的關鍵。對于2.6.29內核來說,已經沒有了devfs的支持,創建設備節點只有通過兩種辦法由文件系統完成:
        1) 制作文件系統鏡像前用mknod手動創建好系統中所有的(包括可能有的)設備節點,并把這些節點文件一起做進文件系統鏡像中;
        2)在文件系統初始化過程中,通過/sys目錄所輸出的信息,在/dev目錄下動態的創建系統中當前實際有的設備節點。
        顯然,方法1)有很大的局限性,僅限于沒有設備動態增加或減少的情況,不適用于很多設備熱插拔的情況,比如U盤,SD卡等等。方法2)是目前大多數PC上Linux的做法(基于udev實現)。這種方法有兩個前提:/sys目錄掛載和一個可寫的/dev目錄。
        這也就是為什么我們在這里需要掛載/sys和ramfs在/dev目錄上。事實上,這種方法最早就是為熱插拔設計的,你可以理解為當系統啟動是,所有設備一下子全部“插入”了進來。
        這里有一點要說明的是,在文件系統初始化跑到這里之前,原本的/dev目錄下必須有一個的設備節點:/dev/console。
        4. 支持熱插拔
        echo /sbin/mdev > /proc/sys/kernel/hotplug
        /sbin/mdev –s
        /bin/hotplug
        這幾個就是用來完成我上面所說的兩個東西:
        1)通過mdev -s 在/dev目錄下建立必要的設備節點;
        2)設置內核的hotplug handler為mdev, 即當設備熱插拔時,由mdev接收來自內核的消息并作出相應的回應, 比如掛載U盤。
        對于mdev,需要注意的是,文件系統里存在/etc/mdev.conf文件,它包含了mdev的配置信息。通過這個文件,我們可以自定義一些設備節點的名稱或鏈接來滿足特定的需要。這是root qtopia中mdev.conf的內容:

        # system all-writable devices
        full 0:0 0666
        null 0:0 0666
        ptmx 0:0 0666
        random 0:0 0666
        tty 0:0 0666
        zero 0:0 0666

        # console devices
        tty[0-9]* 0:5 0660
        vc/[0-9]* 0:5 0660

        # serial port devices
        s3c2410_serial0 0:5 0666 =ttySAC0
        s3c2410_serial1 0:5 0666 =ttySAC1
        s3c2410_serial2 0:5 0666 =ttySAC2
        s3c2410_serial3 0:5 0666 =ttySAC3

        # loop devices
        loop[0-9]* 0:0 0660 =loop/

        # i2c devices
        i2c-0 0:0 0666 =i2c/0
        i2c-1 0:0 0666 =i2c/1

        # frame buffer devices
        fb[0-9] 0:0 0666

        # input devices
        mice 0:0 0660 =input/
        mouse.* 0:0 0660 =input/
        event.* 0:0 0660 =input/
        ts.* 0:0 0660 =input/

        # rtc devices
        rtc0 0:0 0644 >rtc
        rtc[1-9] 0:0 0644

        # misc devices
        mmcblk0p1 0:0 0600 =sdcard */bin/hotplug.sh
        sda1 0:0 0600 =udisk * /bin/hotplug.sh
        可以看到,原本串口驅動注冊的設備名是s3c2410_serial0,s3c2410_serial1和s3c2410_serial2,而mdev則會在/dev目錄下對應生成ttySAC0,ttySAC1和ttySAC2以符合應用程序對于串口設備名稱的習慣。
        同樣的,/dev/sdcard和/dev/udisk永遠分別指向SD卡和U盤的第一個分區。(所以,用那些沒有分區表的SD卡或U盤的兄弟知道原因了吧...)
        5. 掛載一些其它的常用文件系統
        # mounting file system specified in /etc/fstab
        mkdir -p /dev/pts
        mkdir -p /dev/shm
        /bin/mount -n -t devpts none /dev/pts -o mode=0622
        /bin/mount -n -t tmpfs tmpfs /dev/shm
        /bin/mount -n -t ramfs none /tmp
        /bin/mount -n -t ramfs none /var
        mkdir -p /var/empty
        mkdir -p /var/log
        mkdir -p /var/lock
        mkdir -p /var/run
        mkdir -p /var/tmp
        就像注釋中所說的,這是用來掛載其他一些常用的文件系統,并在/var目錄下(同樣是ramfs,可寫的)新建必要的目錄。
        6. 設定系統時間
        /sbin/hwclock -s
        從硬件RTC中獲取,不過似乎有問題接下來就是啟動系統服務了,包括log記錄,網絡, http server和自定義的"跑馬燈服務"...
        【關于mdev.conf的補充說明】
        # misc devices
        mmcblk0p1 0:0 0600 =sdcard */bin/hotplug
        sda1 0:0 0600 =udisk * /bin/hotplug
        這兩句配置的意思是當SD卡或者U盤插入/拔出時,將這個消息傳遞給自定義的熱插拔handler, /bin/hotplug.
        這個程序是友善之臂開發的用于自動掛載可移動設備的,目前是SD卡和U盤。它的邏輯很簡單,將SD卡或者U盤的第一個分區作為FAT/FAT32掛載到/sdcard或者/udisk。
        但這也同時帶來一個問題,當SD卡或者U盤上沒有分區表或者第一個分區不是FAT/FAT32格式的時候,它就玩不轉了,兄弟們要小心了:)
        7. 啟動一系列服務:
        Syslogd
        /etc/rc.d/init.d/netd start
        echo " " > /dev/tty1
        echo "Starting networking..." > /dev/tty1
        sleep 1
        /etc/rc.d/init.d/httpd start
        echo " " > /dev/tty1
        echo "Starting web server..." > /dev/tty1
        sleep 1
        /etc/rc.d/init.d/leds start
        echo " " > /dev/tty1
        echo "Starting leds service..." > /dev/tty1
        echo " "
        sleep 1
        nsyslog - 用于記錄內核和應用程序debug信息
        nnetd - inetd, 一個掛載啟動各種網絡相關服務的看守進程
        nhttpd - http server看守進程
        nleds- 跑馬燈看守進程
        其中,inetd的配置文件為/etc/inetd.conf,這是文件內容:

        # /etc/inetd.conf: see inetd(8) for further informations.
        echo stream tcp nowait root internal
        echo dgram udp wait root internal
        daytime stream tcp nowait root internal
        daytime dgram udp wait root internal
        time stream tcp nowait root internal
        time dgram udp wait root internal

        # These are standard services.
        #
        ftp stream tcp nowait root /usr/sbin/ftpd /usr/sbin/ftpd
        telnet stream tcp nowait root /usr/sbin/telnetd /usr/sbin/telnetd -i
        可以看到,這里啟動的網絡服務有兩個:
        1)ftp server 和
        2)telnet server。
        有關網絡服務的端口和協議等具體信息,可以參考/etc/services, /etc/protocol。
        8. 配置網絡設備(網卡)
        /sbin/ifconfig lo 127.0.0.1/etc/init.d/ifconfig-eth0:
        1)設定本機回環地址為127.0.0.1
        2)運行網卡設置腳本/etc/init.d/ifconfig-eth0
        這是/etc/init.d/ifconfig-eth0的內容, 加入了我的一些注釋
        #!/bin/sh
        echo -n Try to bring eth0 interface up......>/dev/ttySAC0
        #判斷/etc/eth0-setting文件是否存在
        if [ -f /etc/eth0-setting ] ; then
        #讀取配置文件信息
        source /etc/eth0-setting
        #如果根文件系統為nfs,則說明網卡已經配置OK,這里什么都不需要配置了
        if grep -q "^/dev/root / nfs " /etc/mtab ; then echo -n NFS root ... > /dev/ttySAC0
        #否則,根據配置文件中的MAC, IP, Mask和Gateway通過ifconfig命令相應地配置網卡
        else
        ifconfig eth0 down
        ifconfig eth0 hw ether $MAC
        ifconfig eth0 $IP netmask $Mask up
        route add default gw $Gateway fi
        #將配置文件中的DNS設置寫入/etc/resolv.conf使之生效
        echo nameserver $DNS > /etc/resolv.conf
        #配置文件不存在,使用默認配置else
        #如果根文件系統為nfs,則說明網卡已經配置OK,這里什么都不需要配置了
        if grep -q "^/dev/root / nfs " /etc/mtab ; then
        echo -n NFS root ... > /dev/ttySAC0
        else
        #將網卡的IP地址設定為192.168.1.230
        /sbin/ifconfig eth0 192.168.1.230 netmask 255.255.255.0 up
        fi
        fi
        echo Done > /dev/ttySAC0
        可以看到,NFS自動識別就是靠判斷/etc/mtab中是否有nfs的掛載記錄實現的。
        這是root qtopia文件系統中/etc/eth0-settings文件:
        IP=192.168.1.230
        Mask=255.255.255.0
        Gateway=192.168.1.1
        DNS=192.168.1.1
        MAC=08:90:90:90:90:90
        終于到最后了,啟動Qtopia GUI環境
        /bin/qtopia &
        echo " " > /dev/tty1
        echo "Starting Qtopia, please waiting..." > /dev/tty1
        可以看到,這里Qtopia是通過運行/bin/qtopia來啟動的。事實上,/bin/qtopia也是一個腳本,它的任務是設定Qtopia運行必要的環境, 最后通過調用qpe可執行文件真正啟動Qtopia。這是它的全部內容,我加入了一些注釋:

        #!/bin/sh

        export TSLIB_TSDEVICE=/dev/input/event0
        export TSLIB_CONFFILE=/usr/local/etc/ts.conf
        export TSLIB_PLUGINDIR=/usr/local/lib/ts
        export TSLIB_CALIBFILE=/etc/pointercal
        export QTDIR=/opt/Qtopia
        export QPEDIR=/opt/Qtopia
        export PATH=$QTDIR/bin:$PATH
        export LD_LIBRARY_PATH=$QTDIR/lib:/usr/local/lib:$LD_LIBRARY_PATH


        TS_INFO_FILE=/sys/devices/virtual/input/input0/uevent
        if [ -e $TS_INFO_FILE -a "/bin/grep -q TouchScreen < $TS_INFO_FILE" ]; then
        export QWS_MOUSE_PROTO="TPanel:/dev/input/event0 USB:/dev/input/mice"
        if [ -e /etc/pointercal -a ! -s /etc/pointercal ] ; then
        rm /etc/pointercal
        fi
        else
        export QWS_MOUSE_PROTO="USB:/dev/input/mice"
        >/etc/pointercal
        fi
        unset TS_INFO_FILE

        export QWS_KEYBOARD=TTY:/dev/tty1
        export KDEDIR=/opt/kde

        export HOME=/root

        exec $QPEDIR/bin/qpe 1>/dev/null 2>/dev/null
        #!/bin/sh
        #(1)tslib環境變量設置,包括了touchscreen設備文件,tslib配置文件,tslib plug-in位置和touchscreen校準數據文件
        export TSLIB_TSDEVICE=/dev/input/event0
        export TSLIB_CONFFILE=/usr/local/etc/ts.conf
        export TSLIB_PLUGINDIR=/usr/local/lib/ts
        export TSLIB_CALIBFILE=/etc/pointercal
        #(2)Qtopia環境變量設置,設定了Qtopia主要文件位置
        export QTDIR=/opt/Qtopia
        export QPEDIR=/opt/Qtopia
        #(3)設定PATH和LD_LIBRARY_PATH以包含Qtopia的可執行文件和共享庫文件,方便Qtopia正確運行
        export PATH=$QTDIR/bin:$PATH
        export LD_LIBRARY_PATH=$QTDIR/lib:/usr/local/lib:$LD_LIBRARY_PATH
        #(4)通過判斷/sys/devices/virtual/input/input0/uevent中是否包含touchscreen信息使Qtopia自動識別touchscreen和USB鼠標
        TS_INFO_FILE=/sys/devices/virtual/input/input0/uevent
        if [ -e $TS_INFO_FILE -a "/bin/grep -q TouchScreen < $TS_INFO_FILE" ]; then
        export QWS_MOUSE_PROTO="TPanel:/dev/input/event0 USB:/dev/input/mice"
        if [ -e /etc/pointercal -a ! -s /etc/pointercal ] ; then
        rm /etc/pointercal
        fi
        else
        export QWS_MOUSE_PROTO="USB:/dev/input/mice" >/etc/pointercal
        fi
        unset TS_INFO_FILE
        export QWS_KEYBOARD=TTY:/dev/tty1export KDEDIR=/opt/kde
        export HOME=/root
        #(5)通過調用/opt/Qtopia/bin/qpe真正啟動Qtopia
        exec $QPEDIR/bin/qpe 1>/dev/null 2>/dev/null
        到此為止,文件系統從初始化到最終啟動Qtopia GUI環境的全部過程就結束了,大家可以看到,友善之臂的“小秘密”其實都在這里,說穿了很簡單:)只要大家能夠靜下心來認真看看腳本,看看源代碼,加上一些背景知識的了解,搞清楚一個嵌入式系統就這么簡單。
        通常/linuxrc這個文件只有在
        1. 使用了Initial Ramdisk (initrd)
        2. 內核命令行上指定了init=/linuxrc
        這兩種情況下才有用,mini2440的root_qtopia屬于情況2),
        在root_qtopia中,/linuxrc是指向/bin/busybox的符號鏈接,也就是說,整個文件系統的入口就變成了busybox的main()函數,busybox支持這種方式來啟動busybox本身和整個文件系統的初始化。


        評論


        技術專區

        關閉
        主站蜘蛛池模板: 蒙山县| 罗平县| 武宣县| 永川市| 佛山市| 清苑县| 广东省| 东安县| 高台县| 石城县| 五大连池市| 若羌县| 乌兰县| 崇文区| 高陵县| 河西区| 凤翔县| 施秉县| 鄂州市| 泉州市| 宁都县| 和政县| 普定县| 遂溪县| 潜山县| 隆尧县| 金塔县| 诸城市| 思茅市| 龙江县| 荆门市| 岫岩| 伊春市| 万源市| 博客| 大城县| 石景山区| 多伦县| 饶河县| 阿城市| 鄂伦春自治旗|