Linux Kernel 2:用户空间的初始化

上篇咱们知道,kernel初始化后将启动init进程,那么这个进程将干些什么呢?除此以外,kernel还须要作些什么事情呢?(想一想文件系统、根存储设备是在何时初始化的呢?) linux

先从文件系统初始化提及。之前一直不明白,有了kernel为什么还须要一个文件系统?通过反复琢磨,明白一个道理,kernel加载到内存后,kernel运行起来是没有问题的,可是若是没有Root FS,就好像PC上没有硬盘.....。另外,Linux中不少虚拟文件系统(proc,sys,dev等)都是挂靠在RootFS中的,因此RootFS在Linux中更加关键(必要条件简直就是)。(kernel中的FS是另一个庞大的部分) android

一 根文件系统 ubuntu

1 FHS:File system Hierachy Standard:Linux上文件系统布局的标准,例如 usr目录大概是干嘛的,tmp目录大概是干吗的。有空能够瞧瞧....其实使用LINUX OS多了,天然就理解了。 架构

2 经常使用的文件夹布局:其实就是ES上广泛的文件目录: electron

  • bin;dev;etc;home;lib;sbin;tmp;usr;var;

二 Post Boot 函数

这里讲的是execve init以前的事情,由于源码中: 工具

  • run_init_process("/usr/bin/init"):这个时候已经有FS的布局了,也就是init程序自己必须放在一个FS中。

三 init 布局

init进程很重要,不过android上的init进程的工做流程比较简单。这里介绍非Android上的init。通常它读取的配置文件是/etc/inittab中(ubuntu上彷佛没有这个文件了,之后得找个FCore的系统看看)。 spa

另外,这里还有一个叫run level的概念。见图1. 进程

图1 run level

Run level说白了就是将系统运行状态分红几个级别,例如shutdown的时候init须要执行一些操做,reboot的时候须要执行一些操做。

这里关于Init的东西就不介绍了,不少关于linux系统配置的知识都有涉及。(确实比android的init要复杂多了)

四 Initial RAM Disk

LK在早期初始化的过程当中,须要mount一个FS,目前有新旧两种方法:

  • old方法就是使用initial ram disk,也叫initrd

  • new方法就是使用iniramfs

这两个东西很是常见,我们要好好研究下。

4.1 initrd

这个功能须要配置kernel的编译选项。
ARM支持将前面的initrd和vmlinux打包到一个image中。实际上只有ARM架构支持。(内核编译的时候要选择这一项)。讲了这么多,那么到底怎么用呢?

  • initrd也是一个image。由bootloader启动的时候,或者bootloader下载到某个地方

  • bootloader把initrd的地址告诉内核。内核启动时候把这个image解压并挂载

  • 另一种办法,编译的时候将initrd和kernel放到一个image中,这种方法只有ARM架构支持。使用这种办法话,建议用initramfs。注意,android中使用的就是一个kernel+initramfs的单一image。也就是第二种办法

(这里有不少细节问题,之后咱们分析源码再来搞懂它)

BL启动内核的时候,须要给LK传递参数,即告诉LK这个initrd在什么位置...很简单不是?

KL如何使用这个initrd呢?

  • KL先根据参数指定的initrd地址,将这个image拷贝到内存中,而后解压,并挂载为/

  • 找到这个disk中的linuxrc文件,而后执行里边的语句《====这给了咱们定制化本身ES的好计划

  • 处理完linuxrc后,KL unmount这个initrd,并加载真正的root device(看到没,这个initrd就是作些初始化的工做,可是你也能够不umount这个initrd。)这里的处理稍有差别。若是BL在参数中指明root=/dev/ram0,(代码中可见到这些语句),那么KL就不会执行linuxrc,而且也不会umount initrd。也就是这个initrd就是最终的根文件系统了。

那么如何制做这个Initrd呢?

其实就是一个gzip打包的文件夹....

(这部分代码在do_mounts.c中的prepare_namespace函数中)

4.2 initramfs

(详细说明:参考kernel/documentations/filesystems/ramfs-rootfs-initramfs.txt)

kernel默认支持这个initramfs,因此编译的时候,会整一个default的initramfs放到内核中。initramfs是一个cpio的打包文件。我特地查了下cpio的info。通常用法就是:读取一个目录下全部文件的信息及其全部文件的内容(多是直接read数据到一个buffer中),而后把这些信息写到一个文件中。说白了,可能就是一个序列化的工具。而后LK用一样的方法就能够反序列化,恢复原来目录中的内容了。

前面说,LK编译的时候默认会有一个简单的initramfs目录结构。这个结构由kernel/scripts/gen_initramfs_list.sh脚本生成。这个脚本很简单:


dir /dev 0755 0 0

nod /dev/console/ 0600 0 0 c 5 1

dir /root 0700 0 0


执行的时候,前面加上mk...就生成一个目录了,而后用cpio打包,生成iniramfs,最后由LK解包并挂载

(具体内容,参考ramfs-rootfs-initramfs.txt)

如何制做本身的initramfs呢?

  • 搞一个文件夹吧,可仿照PC机器上linux的文件结构。也能够把busybox放上去。

  • find testramfs -depth -print | cpio -ov > testramfs.cpio  cpio的输入是文件名,输出经过>定向到testramfs.cpio。你们能够试试。

  • 解压的话,cpio -ivd < testramfs.cpio。这样就能还原testramfs文件夹中的内容了。

cpio:-o表示output,-v表示打印一些verbose信息,-i表示input,-d表示创建整个文件夹结构。没有-d的话,会出问题。

不过有了kernel编译的支持,咱们不用本身调用cpio了,在编译选项中有一个INITRAMFS_SOURCE,把它指向目标文件夹,编译的时候天然会生成这个initramfs了。

参考文献:

这些参考文献中,最重要的是最后一个,ols2k-9.ps,下载并处理后获得一个pdf,实际上一篇论文。主要介绍了

Linux启动的一些问题。

再三解释一下,为何须要init ram disk。FS通常安装在存储介质上,而读取这些存储介质须要驱动。内核启动的时候若是把这些驱动都加载的话,会很是麻烦,即便你把驱动静态编译到内核中,也不是一个完美的解决办法。因此。先整一个简单的,基于内存的FS,这样初始化工做均可以顺利进行。最后,等驱动都加载完后,再把实际存储上的FS挂载上来。这里要明白一点,没有一个FS的话,LK是无法正常工做的。

五 U-Boot

全名为Das U-Boot,是一个使用很是普遍的Bootloader。之后会专门撰文介绍UB。这里简单说两个点:

  • UB的代码结构,先从CPU的start.S开始,这里会根据不一样的CPU进行初始化,大部分代码都不须要咱们修改

  • 再是Board的启动,这个和具体的板子有关。如今更名叫lowlevel_init.S了。

(最难的部分在于各个设备的初始化了,须要结合开发板的datasheet来作)

这里列出如下参考书:

其中,关于SDRAM.pdf,网址已经移到了:http://www.maxwell.com/products/microelectronics/docs/INTRO_TO_SDRAM.PDF

各位看官能够下载看看。

相关文章
相关标签/搜索