Linux系统启动时使用initramfs (initram file system), initramfs可以在启动早期提供一个用户态环境,借助它可以完成一些内核在启动阶段不易完成的工作。当然initramfs是可选的,Linux中的内核编译选项默认开启initrd。在下面的示例情况中你可能要考虑用initramfs。

  • 加载模块,比如第三方driver
  • 定制化启动过程 (比如打印welcome message等)
  • 制作一个非常小的rescue shell
  • 任何kernel不能做的,但在用户态可以做的 (比如执行某些命令)

一个initramfs至少要包含一个文件,文件名为/init。内核将这个文件执行起来的进程作为main init进程(pid 1)。当内核挂载initramfs后,文件系统的根分区还没有被mount, 这意味着你不能访问文件系统中的任何文件。如果你需要一个shell,必须把shell打包到initramfs中,如果你需要一个简单的工具,比如ls, 你也必须把它和它依赖的库或者模块打包到initramfs中。总之,initramfas是一个完全独立运行的体系。

另外initramfs打包的时候,要求打包成压缩的cpio档案。cpio档案可以嵌入到内核image中,也可以作为一个独立的文件在启动的过程中被GRUB load。

Linux的initramrd img

在/boot目录下的initrd.img-xxx (Ubuntu)或者initramfs-xxx.img (CentOS) 文件即为Linux用的initramfs文件。我们可以将其解压出来看看其目录结构,如下:

# ls -l /boot/
total
-rw-r--r-- root root Jul abi-4.4.--generic
-rw-r--r-- root root Aug abi-4.4.--generic
-rw-r--r-- root root Jul config-4.4.--generic
-rw-r--r-- root root Aug config-4.4.--generic
drwxr-xr-x root root Jul : grub
-rw-r--r-- root root Aug initrd.img-4.4.--generic
-rw-r--r-- root root Aug initrd.img-4.4.--generic
-rw------- root root Jul System.map-4.4.--generic
-rw------- root root Aug System.map-4.4.--generic
-rw------- root root Jul vmlinuz-4.4.--generic
-rw------- root root Aug vmlinuz-4.4.--generic
# initrd的文件类型是gzip压缩文件
# file /boot/initrd.img-4.4.--generic
/boot/initrd.img-4.4.--generic: gzip compressed data, from Unix, last modified: Thu Aug :: 2017
# cp /boot/initrd.img-4.4.--generic .
# 文件大小为22M
# ls -lh initrd.img-4.4.--generic
-rw-r--r-- root root 22M Jul : initrd.img-4.4.--generic
# 修改文件的后缀名,否则gzip工具无法识别
# mv initrd.img-4.4.--generic initrd.img-4.4.--generic.gz
# 用gzip解压缩
# gzip -d initrd.img-4.4.--generic.gz
# 解压后的大小为57M
# ls -lh initrd.img-4.4.--generic
-rw-r--r-- root root 57M Jul : initrd.img-4.4.--generic # 解压后的文件类型为cpio档案
# file initrd.img-4.4.--generic
initrd.img-4.4.--generic: ASCII cpio archive (SVR4 with no CRC) # 将文件从cpio档案中copy出来
# cpio -idmv < initrd.img-4.4.--generic
.
lib64
lib64/ld-linux-x86-.so.
...
lib/systemd
lib/systemd/systemd-udevd
blocks # 最终可以看到如下文件和目录结构,就是initramrd的结构
# ls
bin conf etc init initrd.img-4.4.--generic lib lib64 run sbin scripts

可以看到initramfs和跟分区文件系统的雏形很像,只是它的大小不大,少了很多工具和库。有些内核模块就在其中,比如:/lib/modules/4.4.0-93-generic/kernel/。

qemu中启动"Hello World" initramfs

在前文“在qemu环境中用gdb调试Linux内核”中,已经准备了一个Linux启动环境,但是缺少initramfs。我们可以做一个最简单的Hello World initramfs,来直观地理解initramfs。

Hello World的C程序如下,与普通的Hello World相比,加了一行while(1)。

#include <stdio.h>

void main()
{
printf("Hello World\n");
fflush(stdout);
/* 让程序打印完后继续维持在用户态 */
while(1);
}

编译helloworld.c程序

# gcc -static -o helloworld -m32 helloworld.c
  • -static: On systems that support dynamic linking, this prevents linking with the shared libraries. //不让gcc动态链接shared libraries
  • -m32: Generate code for a 32-bit or 64-bit environment //在前文“在qemu环境中用gdb调试Linux内核”中Linux内核被编译成了32位架构,所以这里在gcc的选项中也编译成32位可执行程序

在64位机器上编译成32位程序,可能会报错如下:

In file included from /usr/include/stdio.h:27:0,
from helloworld.c:2:
/usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
# include <sys/cdefs.h>
^
compilation terminated.

解决方案是安装libc6-dev-i386包。

# apt-get install libc6-dev-i386

打包initramfs文件

# echo helloworld | cpio -o --format=newc > hwinitramfs

在qemu中启动编译好的内核,把hwinitramfs指定为initrd,在-append参数中将init指定为helloworld。

# qemu -kernel linux-3.18./arch/x86/boot/bzImage -initrd hwinitramfs -append "console=ttyS0 rdinit=helloworld" -nographic

系统能成功启动到输出"Hello World",并且在用户态停住。结合前文“在qemu环境中用gdb调试Linux内核”,可以看到qemu虚机中运行的Linux系统已经成功挂载了initramfs, 在console日志中也能看到“Unpacking initramfs...”。

参考

Custom Initramfs

GNU CPIO Manual

Initramfs 原理和实践的更多相关文章

  1. Atitit 管理原理与实践attilax总结

    Atitit 管理原理与实践attilax总结 1. 管理学分类1 2. 我要学的管理学科2 3. 管理学原理2 4. 管理心理学2 5. 现代管理理论与方法2 6. <领导科学与艺术4 7. ...

  2. Atitit.ide技术原理与实践attilax总结

    Atitit.ide技术原理与实践attilax总结 1.1. 语法着色1 1.2. 智能提示1 1.3. 类成员outline..func list1 1.4. 类型推导(type inferenc ...

  3. Atitit.异步编程技术原理与实践attilax总结

    Atitit.异步编程技术原理与实践attilax总结 1. 俩种实现模式 类库方式,以及语言方式,java futuretask ,c# await1 2. 事件(中断)机制1 3. Await 模 ...

  4. Atitit.软件兼容性原理与实践 v5 qa2.docx

    Atitit.软件兼容性原理与实践   v5 qa2.docx 1. Keyword2 2. 提升兼容性的原则2 2.1. What 与how 分离2 2.2. 老人老办法,新人新办法,只新增,少修改 ...

  5. Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法

    Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法 于是我们可以把上面的语法改写成如下形式:1 合并前缀1 语法分析有自上而下和自下而上两种分析 ...

  6. Atitit.gui api自动化调用技术原理与实践

    Atitit.gui api自动化调用技术原理与实践 gui接口实现分类(h5,win gui, paint opengl,,swing,,.net winform,)1 Solu cate1 Sol ...

  7. Atitit.提升语言可读性原理与实践

    Atitit.提升语言可读性原理与实践 表1-1  语言评价标准和影响它们的语言特性1 1.3.1.2  正交性2 1.3.2.2  对抽象的支持3 1.3.2.3  表达性3 .6  语言设计中的权 ...

  8. Atitit 网络爬虫与数据采集器的原理与实践attilax著 v2

    Atitit 网络爬虫与数据采集器的原理与实践attilax著 v2 1. 数据采集1 1.1. http lib1 1.2. HTML Parsers,1 1.3. 第8章 web爬取199 1 2 ...

  9. Atitit.软件兼容性原理与实践 v3 q326.docx

    Atitit.软件兼容性原理与实践 v3 q326.docx 1. 架构兼容性1 2. Api兼容性1 2.1. 新api  vs  修改旧的api1 3. Web方面的兼容性(js,html)1 3 ...

随机推荐

  1. 《PHP和MySQL Web开发》读书笔记(上篇)

    最近过得太浮躁了,实在自己都看不下去了,看了PHP圣经之后,觉得非常有必要要总结一下. Chapter1.快速入门 ·PHP标记:总共有三种风格,常用的还是XML风格为主 <?php echo ...

  2. Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A

    问题: 当我们打开数据库,即use dbname时,要预读数据库信息,当使用-A参数时,就不预读数据库信息. 解决方法:mysql -hhostname -uusername -ppassword - ...

  3. url参数用&拼接并且按照字母顺序排序方法

    private string urlParamManager(JObject postArray, bool flag) { ArrayList keys = new ArrayList(); for ...

  4. zookeeper集群查看状态时报错Error contacting service. It is probably not running的一些坑以及解决办法

    最近在搭建mq集群时候需要用到,zookeeper,可是启动的时候显示成功了,查看状态的时候却报错了: 碰到这个问题也是研究好好半天才解决,这里就总结出一个快速解决办法! 首先,必须看日志: 报错信息 ...

  5. Tomcat的JVM设置和连接数设置

    Windows环境下修改“%TOMCAT_HOME%\bin\catalina.bat”文件,在文件开头增加如下设置:set JAVA_OPTS=-Xms256m -Xmx512m Linux环境下修 ...

  6. 畸形的 dockerfile中的COPY命令-

    dockerfile中的COPY是指COPY 指定目录的“子级目录”下所有的目录和文件,到指定目录中,这个shell中的cp命令大相径庭,使得很多人纳闷,怎么cpy过去的文件不是自己想要的

  7. mysql高可用架构 -> MHA环境准备-02

    环境准备 环境检查(三个测试节点的环境都应该是一样的,只有ip不同) [root@db01 bin]# cat /etc/redhat-release //系统版本 CentOS Linux rele ...

  8. Android性能测试工具之APT

    1.APT工具简介: APT是一个eclipse插件,可以实时监控Android手机上多个应用的CPU.内存数据曲线,并保存数据:另外还支持自动获取内存快照.PMAP文件分析等,方便开发人员自测或者测 ...

  9. 21 JSON and Go go语言和json

    JSON and Go 25 January 2011 Introduction JSON (JavaScript Object Notation) is a simple data intercha ...

  10. python基础学习之路No.2 数据类型

    python中常见的数据类型有:整数.浮点数.字符串.列表.元组.字典 python相较其他语言,可以省略了声明,可以直接定义赋值使用. 例如: a=12 就相当于 其他语言中的  int a=12  ...