某系统root filesystem挂载和init学习
[问题]这算是一个猜想,猜测某系统的启动过程,以及文件系统的挂载方式。
1、根目录下的init应该是第一个init程序。也就是说,内核并没有使用initramfs(因为2.6 kernel里面的initramfs不可以config,这里的没有使用是指将rootfs内容留空,下同);而是直接挂载了squashfs作为root filesystem。
2、支撑前一个猜想的依据有三条:
1)bootloader里的参数设置有root=31:03。只有不使用initramfs机制做init情况下,kernel才会去使用该参数;否则,真正的root file system将会由rootfs中的init来挂载,而不是内核使用“root=”这一参数来挂载。
2)“cat /proc/mounts”,可以看到系统自动挂载rootfs之后,立即就挂载了squashfs。下面是cat /proc/mounts的内容。
rootfs / rootfs rw 0 0 /dev/root / squashfs ro 0 0 none /proc proc rw,nodiratime 0 0 none /sys sysfs rw 0 0 tmpfs /var tmpfs rw 0 0 dev /dev tmpfs rw 0 0 none /dev/pts devpts rw 0 0 none /proc/bus/usb usbfs rw 0 0
3)上面的mount内容和根目录下init脚本内容是一致的,下面根目录下的init脚本内容。
#!/bin/sh # # crucial mountpoints mount -t proc none /proc mount -t sysfs none /sys mount -n tmpfs /var -t tmpfs -o size=8388608 tar cf /tmp/devtmp.tar /dev mount dev /dev -t tmpfs tar xf /tmp/devtmp.tar && rm -f /tmp/devtmp.tar mknod /dev/console c 5 1 mknod /dev/ttyS0 c 4 64 ... mkdir /dev/pts /dev/shm # rest of the mounts mount none /dev/pts -t devpts if [ -e /proc/bus/usb ]; then mount none /proc/bus/usb -t usbfs fi # setup console, consider using ptmx? CIN=/dev/console COUT=/dev/console ...
那么,如果是这样的话,内核是如何通过root=31:03来找到rootfs的呢?对这个过程还不是很清楚,接下来找资料了解下这个过程。
另外,这个init脚本的最后调用了busybox里面的init,唔,顺便也会探究一下这个过程。
关于root=31:03的解释
唔,根据前面的理解,在不使用initramfs情况下,kernel会使用root作为启动参数。而上面cat /proc/mounts结果中的/dev/root就是内核解释该参数的结果。
事实上,在这个过程中,先是由bootloader把启动参数写到内存的某位置,然后linux内核通过boot loader传递过来的 一个指针(cmd_line_ptr)可以获取到这些参数。你在系统启动之初看到的boot argument打印就在这里,接着这些参数会被写到/proc/cmdline里面去,这样应用程序也可以通过/proc/cmdline来看到启动参数。具体解释见:Linux内核自带的文档Documentation/x86/boot.txt 。
然后呢,下面是cat /proc/cmdline的结果:
# cat /proc/cmdline console=tty0 root=31:03 rootfstype=squashfs init=/init mtdparts=ar7240-nor0:256k(u-boot),64k(u-boot-env),1024k(kernel),6528k(rootfs),256k(cfg),64k(EEPROM) panic=3 quiet #
前面一篇文档已经介绍过,root=31:03事实上代表的是mtdblock3,这是应用的Flash设备上的选项。如果是在其它一些block设备上,这个参数可能是一个物理分区(/dev/sda1),或者是一个逻辑分区(I.E. ,LVM Machenism, /dev/VolGroup00/LogVol00), 更有可能是一个RAID设备,当然,支持不支持还得看bootloader。
另外,因为没有initramfs为root file system挂载驱动啥的,所以,kernel编译的时候至少要包含启动root file system所需要的全部驱动。
至于内核得到root参数后,它到底对它做了些什么,本官暂不能断定,择日再审~~~目前把kernel当做一个黑盒子来用。
关于init=/init
由于该系统没有使用initramfs,所以,根据前一篇介绍init的文章,根据"root="的内容挂载root filesystem后,kernel会去找“init=”指向的init程序。
在该文件系统中,这个init就是上面这一个shell,在其最后,它有执行"/sbin/init":
#!/bin/sh
#
# crucial mountpoints
...
echo "...running /sbin/init" exec /sbin/init echo "INTERNAL ERROR!!! Cannot run /sbin/init."
嗯,如果能允许你运行到最后一句,那么和kernel里init部分给爆出panic是一样的性质,终究是init没有完成。但是,init脚本执行的话,就已经不是kernel的工作范畴了。
然后去看看/sbin/init
# ls -l /sbin/init lrwxrwxrwx 1 admin admin 7 Aug 29 10:39 /sbin/init -> busybox
是的,它只是指向busybox的一个软链接。
关于,busybox里的init我们在另一篇文档里进行介绍。