<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > MINI2440啟動(dòng)配置文件/etc/init.d/rcS文件分析

          MINI2440啟動(dòng)配置文件/etc/init.d/rcS文件分析

          作者: 時(shí)間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
          Mini2440啟動(dòng)配置文件說明
          對(duì)于mini2440,雖然root_qtopia這個(gè)文件系統(tǒng)的GUI是基于Qtopia的,但其初始化啟動(dòng)過程卻是由大部分由busybox完成,Qtopia(qpe)只是在啟動(dòng)的最后階段被開啟。
          由于默認(rèn)的內(nèi)核命令行上有init=/linuxrc, 因此,在文件系統(tǒng)被掛載后,運(yùn)行的第一個(gè)程序是根目錄下的linuxrc。這是一個(gè)指向/bin/busybox的鏈接,也就是說,系統(tǒng)起來后運(yùn)行的第一個(gè)程序也就是busybox本身。這種情況下,busybox首先將試圖解析/etc/inittab來獲取進(jìn)一步的初始化配置信息(參考busybox源代碼init/init.c中的parse_inittab()函數(shù))。而事實(shí)上,root_qtopia中并沒有/etc/inittab這個(gè)配置文件,根據(jù)busybox的邏輯,它將生成默認(rèn)的配置(部分):
          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;
          }
          ……
          其中, 最重要的一個(gè),就是new_init_action(SYSINIT, INIT_SCRIPT, ""), 也就決定了接下去初始化的腳本是INIT_SCRIPT所定義的值。這個(gè)宏的默認(rèn)值是"/etc/init.d/rcS"。
          下面是文件系統(tǒng)中/etc/init.d/rcS的內(nèi)容, 也是我們要分析的重點(diǎn)

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

          # 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
          可以看到,原本串口驅(qū)動(dòng)注冊(cè)的設(shè)備名是s3c2410_serial0,s3c2410_serial1和s3c2410_serial2,而mdev則會(huì)在/dev目錄下對(duì)應(yīng)生成ttySAC0,ttySAC1和ttySAC2以符合應(yīng)用程序?qū)τ?strong>串口設(shè)備名稱的習(xí)慣。
          同樣的,/dev/sdcard和/dev/udisk永遠(yuǎn)分別指向SD卡和U盤的第一個(gè)分區(qū)。(所以,用那些沒有分區(qū)表的SD卡或U盤的兄弟知道原因了吧...)
          5. 掛載一些其它的常用文件系統(tǒng)
          # 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
          就像注釋中所說的,這是用來掛載其他一些常用的文件系統(tǒng),并在/var目錄下(同樣是ramfs,可寫的)新建必要的目錄。
          6. 設(shè)定系統(tǒng)時(shí)間
          /sbin/hwclock -s
          從硬件RTC中獲取,不過似乎有問題接下來就是啟動(dòng)系統(tǒng)服務(wù)了,包括log記錄,網(wǎng)絡(luò), http server和自定義的"跑馬燈服務(wù)"...
          【關(guān)于mdev.conf的補(bǔ)充說明】
          # misc devices
          mmcblk0p1 0:0 0600 =sdcard */bin/hotplug
          sda1 0:0 0600 =udisk * /bin/hotplug
          這兩句配置的意思是當(dāng)SD卡或者U盤插入/拔出時(shí),將這個(gè)消息傳遞給自定義的熱插拔handler, /bin/hotplug.
          這個(gè)程序是友善之臂開發(fā)的用于自動(dòng)掛載可移動(dòng)設(shè)備的,目前是SD卡和U盤。它的邏輯很簡單,將SD卡或者U盤的第一個(gè)分區(qū)作為FAT/FAT32掛載到/sdcard或者/udisk。
          但這也同時(shí)帶來一個(gè)問題,當(dāng)SD卡或者U盤上沒有分區(qū)表或者第一個(gè)分區(qū)不是FAT/FAT32格式的時(shí)候,它就玩不轉(zhuǎn)了,兄弟們要小心了:)
          7. 啟動(dòng)一系列服務(wù):
          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 - 用于記錄內(nèi)核和應(yīng)用程序debug信息
          nnetd - inetd, 一個(gè)掛載啟動(dòng)各種網(wǎng)絡(luò)相關(guān)服務(wù)的看守進(jìn)程
          nhttpd - http server看守進(jìn)程
          nleds- 跑馬燈看守進(jìn)程
          其中,inetd的配置文件為/etc/inetd.conf,這是文件內(nèi)容:

          # /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
          可以看到,這里啟動(dòng)的網(wǎng)絡(luò)服務(wù)有兩個(gè):
          1)ftp server 和
          2)telnet server。
          有關(guān)網(wǎng)絡(luò)服務(wù)的端口和協(xié)議等具體信息,可以參考/etc/services, /etc/protocol。
          8. 配置網(wǎng)絡(luò)設(shè)備(網(wǎng)卡)
          /sbin/ifconfig lo 127.0.0.1/etc/init.d/ifconfig-eth0:
          1)設(shè)定本機(jī)回環(huán)地址為127.0.0.1
          2)運(yùn)行網(wǎng)卡設(shè)置腳本/etc/init.d/ifconfig-eth0
          這是/etc/init.d/ifconfig-eth0的內(nèi)容, 加入了我的一些注釋
          #!/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
          #如果根文件系統(tǒng)為nfs,則說明網(wǎng)卡已經(jīng)配置OK,這里什么都不需要配置了
          if grep -q "^/dev/root / nfs " /etc/mtab ; then echo -n NFS root ... > /dev/ttySAC0
          #否則,根據(jù)配置文件中的MAC, IP, Mask和Gateway通過ifconfig命令相應(yīng)地配置網(wǎng)卡
          else
          ifconfig eth0 down
          ifconfig eth0 hw ether $MAC
          ifconfig eth0 $IP netmask $Mask up
          route add default gw $Gateway fi
          #將配置文件中的DNS設(shè)置寫入/etc/resolv.conf使之生效
          echo nameserver $DNS > /etc/resolv.conf
          #配置文件不存在,使用默認(rèn)配置else
          #如果根文件系統(tǒng)為nfs,則說明網(wǎng)卡已經(jīng)配置OK,這里什么都不需要配置了
          if grep -q "^/dev/root / nfs " /etc/mtab ; then
          echo -n NFS root ... > /dev/ttySAC0
          else
          #將網(wǎng)卡的IP地址設(shè)定為192.168.1.230
          /sbin/ifconfig eth0 192.168.1.230 netmask 255.255.255.0 up
          fi
          fi
          echo Done > /dev/ttySAC0
          可以看到,NFS自動(dòng)識(shí)別就是靠判斷/etc/mtab中是否有nfs的掛載記錄實(shí)現(xiàn)的。
          這是root qtopia文件系統(tǒng)中/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
          終于到最后了,啟動(dòng)Qtopia GUI環(huán)境
          /bin/qtopia &
          echo " " > /dev/tty1
          echo "Starting Qtopia, please waiting..." > /dev/tty1
          可以看到,這里Qtopia是通過運(yùn)行/bin/qtopia來啟動(dòng)的。事實(shí)上,/bin/qtopia也是一個(gè)腳本,它的任務(wù)是設(shè)定Qtopia運(yùn)行必要的環(huán)境, 最后通過調(diào)用qpe可執(zhí)行文件真正啟動(dòng)Qtopia。這是它的全部內(nèi)容,我加入了一些注釋:

          #!/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環(huán)境變量設(shè)置,包括了touchscreen設(shè)備文件,tslib配置文件,tslib plug-in位置和touchscreen校準(zhǔn)數(shù)據(jù)文件
          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環(huán)境變量設(shè)置,設(shè)定了Qtopia主要文件位置
          export QTDIR=/opt/Qtopia
          export QPEDIR=/opt/Qtopia
          #(3)設(shè)定PATH和LD_LIBRARY_PATH以包含Qtopia的可執(zhí)行文件和共享庫文件,方便Qtopia正確運(yùn)行
          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自動(dòng)識(shí)別touchscreen和USB鼠標(biāo)
          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)通過調(diào)用/opt/Qtopia/bin/qpe真正啟動(dòng)Qtopia
          exec $QPEDIR/bin/qpe 1>/dev/null 2>/dev/null
          到此為止,文件系統(tǒng)從初始化到最終啟動(dòng)Qtopia GUI環(huán)境的全部過程就結(jié)束了,大家可以看到,友善之臂的“小秘密”其實(shí)都在這里,說穿了很簡單:)只要大家能夠靜下心來認(rèn)真看看腳本,看看源代碼,加上一些背景知識(shí)的了解,搞清楚一個(gè)嵌入式系統(tǒng)就這么簡單。
          通常/linuxrc這個(gè)文件只有在
          1. 使用了Initial Ramdisk (initrd)
          2. 內(nèi)核命令行上指定了init=/linuxrc
          這兩種情況下才有用,mini2440的root_qtopia屬于情況2),
          在root_qtopia中,/linuxrc是指向/bin/busybox的符號(hào)鏈接,也就是說,整個(gè)文件系統(tǒng)的入口就變成了busybox的main()函數(shù),busybox支持這種方式來啟動(dòng)busybox本身和整個(gè)文件系統(tǒng)的初始化。


          評(píng)論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();