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自身和整个文件体系的初始化。