主题 : mini2440 root_qtopia 文件系统启动过程分析 复制链接 | 浏览器收藏 | 打印
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
贡献值: 71 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
楼主  发表于: 2009-04-29 23:17

 mini2440 root_qtopia 文件系统启动过程分析

管理提醒: 本帖被 kasim 执行置顶操作(2012-02-27)
对于mini2440最新的root_qtopia文件系统启动过程,我在这里做了一些简单的分析,和大家分享一下经验,不足之处也请大家及时指出。
其实,虽然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的逻辑,它将生成默认的配置

复制代码
  1. static void parse_inittab(void)
  2. {
  3. #if ENABLE_FEATURE_USE_INITTAB
  4. char *token[4];
  5. parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
  6. if (parser == NULL)
  7. #endif
  8. {
  9. /* No inittab file -- set up some default behavior */
  10. /* Reboot on Ctrl-Alt-Del */
  11. new_init_action(CTRLALTDEL, "reboot", "");
  12. /* Umount all filesystems on halt/reboot */
  13. new_init_action(SHUTDOWN, "umount -a -r", "");
  14. /* Swapoff on halt/reboot */
  15. if (ENABLE_SWAPONOFF)
  16. new_init_action(SHUTDOWN, "swapoff -a", "");
  17. /* Prepare to restart init when a QUIT is received */
  18. new_init_action(RESTART, "init", "");
  19. /* Askfirst shell on tty1-4 */
  20. new_init_action(ASKFIRST, bb_default_login_shell, "");
  21. //TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
  22. new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
  23. new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
  24. new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
  25. /* sysinit */
  26. new_init_action(SYSINIT, INIT_SCRIPT, "");
  27. return;
  28. }



其中, 最重要的一个,就是new_init_action(SYSINIT, INIT_SCRIPT, ""), 也就决定了接下去初始化的脚本是INIT_SCRIPT所定义的值。这个宏的默认值是"/etc/init.d/rcS".

下面是文件系统中/etc/init.d/rcS的内容, 也是我们要分析的重点
复制代码
  1. #! /bin/sh
  2. PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
  3. runlevel=S
  4. prevlevel=N
  5. umask 022
  6. export PATH runlevel prevlevel
  7. #
  8. # Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
  9. #
  10. trap ":" INT QUIT TSTP
  11. /bin/hostname FriendlyARM
  12. /bin/mount -n -t proc none /proc
  13. /bin/mount -n -t sysfs none /sys
  14. /bin/mount -n -t usbfs none /proc/bus/usb
  15. /bin/mount -t ramfs none /dev
  16. echo /sbin/mdev > /proc/sys/kernel/hotplug
  17. /sbin/mdev -s
  18. /bin/hotplug
  19. # mounting file system specified in /etc/fstab
  20. mkdir -p /dev/pts
  21. mkdir -p /dev/shm
  22. /bin/mount -n -t devpts none /dev/pts -o mode=0622
  23. /bin/mount -n -t tmpfs tmpfs /dev/shm
  24. /bin/mount -n -t ramfs none /tmp
  25. /bin/mount -n -t ramfs none /var
  26. mkdir -p /var/empty
  27. mkdir -p /var/log
  28. mkdir -p /var/lock
  29. mkdir -p /var/run
  30. mkdir -p /var/tmp
  31. /sbin/hwclock -s
  32. syslogd
  33. /etc/rc.d/init.d/netd start
  34. echo " " > /dev/tty1
  35. echo "Starting networking..." > /dev/tty1
  36. sleep 1
  37. /etc/rc.d/init.d/httpd start
  38. echo " " > /dev/tty1
  39. echo "Starting web server..." > /dev/tty1
  40. sleep 1
  41. /etc/rc.d/init.d/leds start
  42. echo " " > /dev/tty1
  43. echo "Starting leds service..." > /dev/tty1
  44. echo " "
  45. sleep 1
  46. /sbin/ifconfig lo 127.0.0.1
  47. /etc/init.d/ifconfig-eth0
  48. /bin/qtopia &
  49. echo " " > /dev/tty1
  50. echo "Starting Qtopia, please waiting..." > /dev/tty1


下面就逐个来分析:
复制代码
  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,相当于把原本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。

好了,今天先写到这里,明天继续:)
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."