linux initramfs,Linux INITRAMFS 与 INITRD「建议收藏」

linux initramfs,Linux INITRAMFS 与 INITRD「建议收藏」initramfs文件生效的过程大致分为四步:第一步:Kernel首先要注册一个RAMFS文件系统类型(实际注册的类型名称是”ROOTFS”,后续我们可以看到它实际上就是”RAMFS”);第二步:然后加载(mount)一个空的rootfs文件系统,类型就是上面提到的RAMFS(ROOTFS);第三步:寻址initramfs文件“XXX.cpio.gz”并解压到已mount的rootfs文件系统中;…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

initramfs文件生效的过程大致分为四步:

第一步:Kernel首先要注册一个RAMFS文件系统类型(实际注册的类型名称是”ROOTFS”,后续我们可以看到它实际上就是”RAMFS”);

第二步:然后加载(mount)一个空的rootfs文件系统,类型就是上面提到的RAMFS(ROOTFS);

第三步:寻址initramfs文件“XXX.cpio.gz”并解压到已mount的rootfs文件系统中;

第四步:寻址用户空间的init,并执行init进程;

第一步和第二步的调用堆栈如下:

init/main.c: start_kernel() ->

fs/dcache.c: vfs_caches_init() ->

fs/namespace.c: mnt_init() {

// The last 2 lines

init_rootfs();

init_mount_tree();

}

在“fs/ramfs/inode.c: init_rootfs()”函数中,注册了”ROOTFS”文件系统类型。通过阅读inode.c源码,发现”ROOTFS”就是”RAMFS”,几乎没有区别。

在“fs/namespace.c: init_mount_tree()”函数中,加载了一个类型为ROOTFS的空root:

mnt

= do_kern_mount(“rootfs”, 0, “rootfs”, NULL);

//第一个rootfs引用文件系统类型ROOTFS,即RAMFS。第二个rootfs为mount entry。

第三步(寻址initramfs文件XXX.cpio.gz,并解压)的调用堆栈如下:

kernel/init/main.c: start_kernel() {

vfs_caches_init();

//

The last line

rest_init();

}

kernel/init/main.c: rest_init() {

kernel_thread(kernel_init, NULL,

CLONE_FS | CLONE_SIGHAND);

}

kernel/init/main.c: kernel_init() {

do_basic_setup();

}

kernel/init/main.c: rest_init() {

do_initcalls();

}

// OK

kernel/init/initramfs.c:populate_rootfs() {

// Decompress the .gz into

‘rootfs’

}

rootfs_initcall(populate_rootfs);

检查populate_rootfs做了什么,它通过__initramfs_start指针和__initramfs_end指针访问XXX.cpio.gz文件,调用函数unpack_to_rootfs函数把源文件解压到rootfs中。gunzip执行解压过程,do_name()/do_copy/do_symlink/do_XXX为解压过程回调函数,在这些do_XXX回调函数中,看到大量使用sys_open/sys_write/sys_XXX函数创建、读写、更改文件和目录及其权限。sys_open/sys_write/sys_read实际上是用户空间open/write/read函数系统调用的实现。

至此,一个完整的rootfs已在目标系统的内存中。

第四步(寻址并运行用户空间INIT进程)的调用堆栈:

init/main.c: kernel_init() {

// At the bottom lines

if (!ramdisk_execute_command)

ramdisk_execute_command = “/init”;

}

kernel/init/main.c: init_post() {

if (ramdisk_execute_command) {

run_init_process(ramdisk_execute_command);

}

}

kernel/init/main.c: run_init_process() {

kernel_execve(init_filename,

argv_init, envp_init);

}

也就是说,只要initramfs文件“XXX.cpio.gz”的根目录下有一个有效的init,或者一个对init有效的链接,Kernel就能启动这个rootfs。那假如说initramfs的rootfs为空(CONFIG_INITRAMFS_SOURCE没有配置或者指向不存在的位置),或者initramfs的rootfs没有有效的“/init”文件。则Kernel会解析commandline,尝试从MTD/UBI之类的NAND分区启动,或者启动INITRAMDISK,或者NFS启动(如果开启了此功能),其调用堆栈如下:

kernel/init/main.c: kernel_init() {

// …

if (!ramdisk_execute_command)

ramdisk_execute_command =

“/init”;

if (sys_access((const char __user

*) ramdisk_execute_command, 0) != 0) {

ramdisk_execute_command =

NULL;

prepare_namespace();

}

// …

}

kernel/init/do_mounts.c:

prepare_namespace() {

// …

if (saved_root_name[0]) {

root_device_name =

saved_root_name;

if

(!strncmp(root_device_name, “mtd”, 3) ||

!strncmp(root_device_name, “ubi”,

3)) {

mount_block_root(root_device_name,

root_mountflags);

goto out;

}

ROOT_DEV =

name_to_dev_t(root_device_name);

if

(strncmp(root_device_name, “/dev/”, 5) == 0)

root_device_name +=

5;

}

if (initrd_load())

goto out;

// …

mount_root() {

// …

mount_nfs_root();

// …

}

// …

}

再来总结一下INITRAMFS的特点:

lROOTFS和RAMFS文件系统在同一个源码文件“inode.c”中实现,他们基本一致,通过Kernel文档也能说明这一点。同时,这也应证了配置Kernel的时候为什么只需要配置’CONFIG_INITRAMFS_SOURCE’一个选项足也。

lROOTFS文件系统类型的注册,以及rootfs的加载,initramfs的解压加载过程,都是Kernel启动过程的默认行为,menuconfig中没有任何选项可以开关。

l实际上rootfs不仅为INITRAMFS提供服务,它还为INITRAMDISK的加载提供中转服务,这一过程后面会讲到。

linitramfs默认启动“/init”,请确保在那个位置有一个有效的init或者是链接。

linitramfs的处理总是优先于对commandLine中启动参数的处理,因此initramfs和commandline无关。当最终的zImage包含了一个有效的XXX.cpio.gz时,不管bootloader传给kernel什么样的commandline,Kernel都会从initramfs启动,比如:

bootargs=root=/dev/mtdblock5 rootfstype=yaffs2 init=/init

console=ttySAC0,115200

//即使当前mtdblock5有一个完整的yaffs2文件系统并且其’/init’也有效’.当前Kernel也会尝试优先启动initramfs。

bootargs=console=ttySAC0,115200

//即使没有指定root/rootfstype/init选项,当前kernel也会尝试自带的initramfs。

l当initramfs没有有效的root时,Kernel才会根据commandline的配置,尝试从mtd/ubi等NAND分区,或者是从ramdisk设备文件,或者是从nfs服务器加载root。

3. Kernel 2.4 armnommu平台对INITRAMDISK的处理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/169687.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • MYSQL数据库同步工具

    MYSQL数据库同步工具MYSQL数据库同步工具MYSQL数据库同步工具功能说明配图MYSQL数据库同步工具GIT地址:https://gitee.com/michlee/mysql-sync功能目前仅针对Mysql数据库1.表结构同步(支持1对多数据库配置:新表/单表/多表/全表(注:多配置全表同步速度会慢一点))2.视图同步(支持1对多数据库配置)3.函数同步(支持1对多数据库配置)4.数据全量同步(1对1数据库配置,支持多表)5.本地启动http://localhost:8765/

    2022年6月15日
    61
  • win10关闭端口占用[通俗易懂]

    win10关闭端口占用[通俗易懂]查看win10所有占用端口公式:查看所有:netstat-ano查看对应端口:netstat-ano|findstr"9004"关闭端口:任务管理器中的详细信息对应的PID就是占用的端口关闭即可命令行关闭端口:taskkill-PID进程号-F进程号为19216…

    2022年7月20日
    18
  • 数据库三大范式通俗解释[通俗易懂]

    数据库三大范式通俗解释[通俗易懂]一范式就是属性不可分割。属性是什么?就是表中的字段。不可分割的意思就按字面理解就是最小单位,不能再分成更小单位了。这个字段只能是一个值,不能被拆分成多个字段,否则的话,它就是可分割的,就不符合一范式。不过能不能分割并没有绝对的答案,看需求,也就是看你的设计目标而定。举例:学生信息组成学生信息表,有姓名、年龄、性别、学号等信息组成。姓名不可拆分吧?所以可以作为该表的一个字段。但我要说这…

    2025年7月14日
    4
  • UVA11100- The Trip, 2007

    UVA11100- The Trip, 2007

    2021年9月8日
    48
  • mac笔记本卡顿怎么办_电脑卡顿不流畅怎么办

    mac笔记本卡顿怎么办_电脑卡顿不流畅怎么办打开活动监视器,(启动台–其他–活动监测器),可以看到耗CPU,内存的具体应用都有哪些。如果能查到就往这方面去停止运行。一般都是图形的操作特别耗内存,可以关闭adboe的一些配置。我出现问题是安装了PS,他的adobe监听实时更新耗了系统70%内存。……

    2025年9月6日
    7
  • 一周第四次课(3月22日)1.13 单用户模式 1.14 救援模式 1.15 克隆虚拟机 1.16 Linux机器相互登录…

    一周第四次课(3月22日)1.13 单用户模式 1.14 救援模式 1.15 克隆虚拟机 1.16 Linux机器相互登录…

    2021年5月25日
    128

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号