span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }.cm-searching {background: #ffa; background: rgba(255, 255, 0, .4);}.cm-force-border { padding-right: .1px; }@media print { .CodeMirror div.CodeMirror-cursors {visibility: hidden;}}.cm-tab-wrap-hack:after { content: ""; }span.CodeMirror-selectedtext { background: none; }.CodeMirror-activeline-background, .CodeMirror-selected {transition: visibility 0ms 100ms;}.CodeMirror-blur .CodeMirror-activeline-background, .CodeMirror-blur .CodeMirror-selected {visibility:hidden;}.CodeMirror-blur .CodeMirror-matchingbracket {color:inherit !important;outline:none !important;text-decoration:none !important;}.CodeMirror-sizer {min-height:auto !important;}
-->
li {list-style-type:decimal;}.wiz-editor-body ol.wiz-list-level2 > li {list-style-type:lower-latin;}.wiz-editor-body ol.wiz-list-level3 > li {list-style-type:lower-roman;}.wiz-editor-body blockquote {padding: 0 12px;}.wiz-editor-body blockquote > :first-child {margin-top:0;}.wiz-editor-body blockquote > :last-child {margin-bottom:0;}.wiz-editor-body img {border:0;max-width:100%;height:auto !important;margin:2px 0;}.wiz-editor-body table {border-collapse:collapse;border:1px solid #bbbbbb;}.wiz-editor-body td,.wiz-editor-body th {padding:4px 8px;border-collapse:collapse;border:1px solid #bbbbbb;min-height:28px;word-break:break-word;box-sizing: border-box;}.wiz-hide {display:none !important;}
-->

环境

Qemu:QEMU emulator version 3.1.0
Linux:Linux-4.14.13
工具链:arm-none-linux-gnueabi-gcc  (gcc version 4.8.3 20140320)
Android:7.1.2
busybox:BusyBox v1.24.2
 

概述

         Android系统使用的根文件系统是用mkbootfs和minigzip制作的,其中mkbootfs用于将根文件系统打包成cpio格式,也可以用cpio工具来打包,将来Linux内核在启动时会调用init/initramfs.c中的函数unpack_to_rootfs对cpio格式进行解包[调用路径:start_kernel --> rest_init --> kernel_init --> kernel_init_freeable --> do_basic_setup --> do_initcalls --> do_initcall_level --> do_one_initcall --> populate_rootfs --> unpack_to_rootfs],在内存中构造出根文件系统结构,mkbootfs工具是Android自己实现的,支持的功能也比cpio弱很多。minigzip也是Android实现的一个压缩工具,是对gzip的简化。
        minigzip的源码位于:external/zlib/
        mkbootfs的源码位于:system/core/cpio/mkbootfs.c
        不过需要注意mkbootfs的功能要比cpio弱,从mkbootfs.c的代码注释中可以看出来:
/* NOTES
**
** - see buffer-format.txt from the linux kernel docs for
** an explanation of this file format
** - dotfiles are ignored
** - directories named 'root' are ignored
** - device notes, pipes, etc are not supported (error)
*/

    上面的信息说明了如下几点:

1. 对cpio格式的说明,Linux内核文档Documentation/early-userspace/buffer-format.txt中有详细说明说明:
The full format of the initramfs buffer is defined by the following
grammar, where:
* is used to indicate "0 or more occurrences of"
(|) indicates alternatives
+ indicates concatenation
GZIP() indicates the gzip() of the operand
ALGN(n) means padding with null bytes to an n-byte boundary initramfs := ("\0" | cpio_archive | cpio_gzip_archive)* cpio_gzip_archive := GZIP(cpio_archive) cpio_archive := cpio_file* + (<nothing> | cpio_trailer) cpio_file := ALGN() + cpio_header + filename + "\0" + ALGN() + data cpio_trailer := ALGN() + cpio_header + "TRAILER!!!\0" + ALGN()

2. 名为"."的文件会被忽略,不会进行打包。

3. 名为"root"的文件也会被忽略,不会进行打包。
4. 不支持设备节点以及管道文件。所以在使用mkbootfs时,需要确保被打包的路径下没有这两种文件,否者会导致错误,并且Linux内核也无法正常访问指定的文件。
 
   此外,在使用mkbootfs时还需要注意的时,mkbootfs会对打包的文件的权限以及uid和gid进行修改(在函数fix_stat中),有可能会遇到本来具备可执行权限的文件,在用mkbootfs打包成cpio格式后,该文件的可执行权限丢失了,比如/etc/init.d/rcS。
 

用法

lib_path=`readlink -f ./lib`
bin_path=`readlink -f ./bin/` export LD_LIBRARY_PATH=${lib_path}:$LD_LIBRARY_PATH
export PATH=${bin_path}:$PATH rm -f ramdisk.img ramdisk.cpio
rm -rf ./tmp/ # pack
pushd rootfs2
mkbootfs -f ../config.txt . | minigzip > ../ramdisk.img
mkbootfs -f ../config.txt . > ../ramdisk.cpio
popd # unpack
mkdir -p tmp
pushd tmp
cpio -i < ../ramdisk.cpio
popd

其中config.txt是一个配置文件,内容如下:

etc/init.d/rcS
   

第1行,把"etc/init.d/rcS"文件的uid设置为0,gid设置为0,权限设置为0755

第2行,所有其他文件的uid都设置0,gid也设置为0,权限设置为0744
需要注意的是,第2行开始有一个空格,并且需要放在最后一行,对具体文件的设置要放到前面。详见mkbootfs.c中函数read_canned_config。
 
    如果没有个指定config.txt,那么会使用Android代码中自带的配置机制[在fix_stat中会调用fs_config],功能要比config.txt更完善,如果在使用mkbootfs时还设置了-d <path>,那么函数fs_config会优先使用<path>/system/etc/fs_config_dirs和<path>/system/etc/fs_config_files中描述的规则,前者针对目录,后者针对其他文件。如果没有给mkbootfs传递-d <path>参数,那么使用Android在源码中指定的规则,它们存放在两个数组中,一个针对目录,一个针对其他文件:
 
针对目录的配置规则:
/* Rules for directories.
** These rules are applied based on "first match", so they
** should start with the most specific path and work their
** way up to the root.
*/ static const struct fs_path_config android_dirs[] = {
{ , AID_SYSTEM, AID_CACHE, , "cache" },
{ , AID_ROOT, AID_ROOT, , "config" },
{ , AID_SYSTEM, AID_SYSTEM, , "data/app" },
{ , AID_SYSTEM, AID_SYSTEM, , "data/app-private" },
{ , AID_SYSTEM, AID_SYSTEM, , "data/app-ephemeral" },
{ , AID_ROOT, AID_ROOT, , "data/dalvik-cache" },
{ , AID_SYSTEM, AID_SYSTEM, , "data/data" },
{ , AID_SHELL, AID_SHELL, , "data/local/tmp" },
{ , AID_SHELL, AID_SHELL, , "data/local" },
{ , AID_SYSTEM, AID_MISC, , "data/misc" },
{ , AID_DHCP, AID_DHCP, , "data/misc/dhcp" },
{ , AID_SHARED_RELRO, AID_SHARED_RELRO, , "data/misc/shared_relro" },
{ , AID_MEDIA_RW, AID_MEDIA_RW, , "data/media" },
{ , AID_MEDIA_RW, AID_MEDIA_RW, , "data/media/Music" },
{ , AID_ROOT, AID_SHELL, , "data/nativetest" },
{ , AID_ROOT, AID_SHELL, , "data/nativetest64" },
... ...

针对其他文件的规则:

static const struct fs_path_config android_files[] = {
{ , AID_ROOT, AID_SHELL, , "system/etc/init.goldfish.rc" },
{ , AID_ROOT, AID_SHELL, , "system/etc/init.goldfish.sh" },
{ , AID_ROOT, AID_SHELL, , "system/etc/init.ril" },
{ , AID_ROOT, AID_ROOT, , "system/etc/ppp/*" },
{ , AID_ROOT, AID_ROOT, , "system/etc/rc.*" },
{ , AID_ROOT, AID_ROOT, , "system/etc/recovery.img" },
{ , AID_ROOT, AID_ROOT, , conf_dir + },
{ , AID_ROOT, AID_ROOT, , conf_file + },
{ , AID_SYSTEM, AID_SYSTEM, , "data/app/*" },
{ , AID_MEDIA_RW, AID_MEDIA_RW, , "data/media/*" },
{ , AID_SYSTEM, AID_SYSTEM, , "data/app-private/*" },
{ , AID_SYSTEM, AID_SYSTEM, , "data/app-ephemeral/*" },
{ , AID_APP, AID_APP, , "data/data/*" },
{ , AID_ROOT, AID_SHELL, , "data/nativetest/tests.txt" },
{ , AID_ROOT, AID_SHELL, , "data/nativetest64/tests.txt" },
... ...

验证

1.  使用压缩格式的ramdisk.img (mkbootfs -f ../config.txt . | minigzip > ../ramdisk.img)
kernel_dir=./Linux-4.14.
kernel_image=${kernel_dir}/arch/arm/boot/zImage
dtb_image=${kernel_dir}/arch/arm/boot/dts/vexpress-v2p-ca9.dtb
qemu_path=/home/pengdonglin/disk_ext/Qemu/qemu-3.1./build/install/bin ${qemu_path}/qemu-system-arm \
-M vexpress-a9 \
-m 1024M \
-smp \
-kernel ${kernel_image} \
-nographic \
-append "root=/dev/ram0 rw rootfstype=ramfs console=ttyAMA0 init=/init ignore_loglevel" \
-initrd ./rootfs/ramdisk.img \
-dtb ${dtb_image}
部分启动log:
[    0.609270] Trying to unpack rootfs image as initramfs...
[ 0.965940] Freeing initrd memory: 3616K
 
2. 使用非压缩的ramdisk.cpio (mkbootfs -f ../config.txt . > ../ramdisk.cpio)
kernel_dir=./Linux-4.14.
kernel_image=${kernel_dir}/arch/arm/boot/zImage
dtb_image=${kernel_dir}/arch/arm/boot/dts/vexpress-v2p-ca9.dtb
qemu_path=/home/pengdonglin/disk_ext/Qemu/qemu-3.1./build/install/bin ${qemu_path}/qemu-system-arm \
-M vexpress-a9 \
-m 1024M \
-smp \
-kernel ${kernel_image} \
-nographic \
-append "root=/dev/ram0 rw rootfstype=ramfs console=ttyAMA0 init=/init ignore_loglevel" \
-initrd ./rootfs/ramdisk.cpio \
-dtb ${dtb_image}
 
部分启动log:
[    0.610055] Trying to unpack rootfs image as initramfs...
[ 0.760468] Freeing initrd memory: 7040K
此外,Linux内核本身也支持在编译时将指定的外部根文件系统编译成cpio.gz格式,然后跟Linux内核链接到一起,在启动时就不需要指定initrd了,Linux内核支持的打包工具usr/gen_init_cpio.c也比mkbootfs强大:
配置内核:
General setup --->
        [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
        (/home/pengdonglin/aarch32/rootfs/rootfs) Initramfs source file(s)
 
Linux内核对这部分的处理请参考usr/Makefile,下面是加入上面的配置之后的部分内核编译log:
  GEN     usr/initramfs_data.cpio.gz
GZIP kernel/config_data.gz
CHK kernel/config_data.h
UPD kernel/config_data.h
CC kernel/configs.o
AR kernel/built-in.o
AS usr/initramfs_data.o
AR usr/built-in.o
展开:
/bin/bash ./scripts/gen_initramfs_list.sh -o usr/initramfs_data.cpio.gz  -u   -g   /home/pengdonglin/disk_ext/Qemu/aarch32/rootfs/rootfs
下面是测试命令:
kernel_dir=./Linux-4.14.
kernel_image=${kernel_dir}/arch/arm/boot/zImage
dtb_image=${kernel_dir}/arch/arm/boot/dts/vexpress-v2p-ca9.dtb
qemu_path=/home/pengdonglin/disk_ext/Qemu/qemu-3.1./build/install/bin ${qemu_path}/qemu-system-arm \
-M vexpress-a9 \
-m 1024M \
-smp \
-kernel ${kernel_image} \
-nographic \
-append "root=/dev/ram0 rw rootfstype=ramfs console=ttyAMA0 init=/init ignore_loglevel" \
-dtb ${dtb_image}
此外,在Documentation/filesystems/ramfs-rootfs-initramfs.txt提供了一个使用cpio打包的脚本:
   #!/bin/sh

   # Copyright  Rob Landley <rob@landley.net> and TimeSys Corporation.
# Licensed under GPL version if [ $# -ne ]
then
echo "usage: mkinitramfs directory imagename.cpio.gz"
exit
fi if [ -d "$1" ]
then
echo "creating $2 from $1"
(cd "$1"; find . | cpio -o -H newc | gzip) > "$2"
else
echo "First argument must be a directory"
exit
fi
完。

使用mkbootfs制作ramdisk根文件系统的更多相关文章

  1. Ramdisk根文件系统映像的修改与创建

    本文简述Ramdisk根文件系统映像的修改以及创建,并附相关脚本以实现自动化配置,而根文件系统的制作过程请网上自行搜索.相关过程尽可能以图的方式展示出来,重在说明操作的过程,仅供参考. Ramdisk ...

  2. 使用BusyBox制作linux根文件系统(CramFS+mdev)

    转:http://www.360doc.com/content/10/0428/11/496343_25245348.shtml 操作系统:Ubuntu9.04 内核版本:linux-2.6.24.7 ...

  3. 嵌入式linux内核制作、根文件系统制作

    嵌入式系统构成: 主要由bootloader.kernel.以及根文件系统三部分组成. 内核制作步骤: 制作嵌入式平台使用的linux内核制作方法与pc平台上的linux内核基本一致 1.清除原有配置 ...

  4. 制作linux根文件系统

    转载地址:http://wenku.baidu.com/view/2cb1b4707fd5360cba1adb14.html 2011十一月 24 转 嵌入式根文件系统制作 (3985) (0) 转自 ...

  5. 使用BusyBox制作Linux根文件系统

    STEP 1:构建目录结构 创建根文件系统目录,主要包括以下目录/dev  /etc /lib  /usr  /var /proc /tmp /home /root /mnt /bin  /sbin  ...

  6. 制作ramdisk-u.img根文件系统

    具体步骤如下:1.解压内核源码树解压linux-2.6.29-mini2440-20090708.tgz到自己的工作目录,会生成一个友善之臂修改过的并且有几个mini2440默认配置文件的内核源码目录 ...

  7. 从ramdisk根文件系统启动Linux成功,及使用initramfs启动linux

    下面两篇文章是ARM9论坛上的讲解ramdisk文件系统的很不错的文章 今天做了个试验,让Linux2.6.29.4从ramdisk根文件系统启动成功,总结一下. 其中涉及的内容较多,很多东西不再详述 ...

  8. 从ramdisk根文件系统启动Linux 二

    今天做了个试验,让Linux2.6.29.4从ramdisk根文件系统启动成功,总结一下.其中涉及的内容较多,很多东西不再详述,如需深入研究请查阅相关资料(百度或谷歌一下一大堆). 开发环境:Fedo ...

  9. 从ramdisk根文件系统启动Linux成功

    这几天参考国嵌的实验手册和网上的资料完成了u-boot定制.内核定制.ramdisk根文件系统的制作,并成功.趁热打铁,总结一下.本文引用了很多网络上的文章,就不一一注明了.感谢各大侠的帮助,如有雷同 ...

随机推荐

  1. js去掉前后空格

    //去前后空格 data=data.replace(/(^\s*)|(\s*$)/g, "");

  2. <%= %>、<% %>、<%@ %>和<%# %>的区别

    轉至http://blog.csdn.net/wildfeng04/article/details/7290126 <%=%> 里面放的变量名 <% %> 中间一般放函数或者方 ...

  3. spring的webutils包。适用于访问httpservletrequest和httpservletresponse

    WebUtils位 于 org.springframework.web.util 包中的 WebUtils 是一个非常好用的工具类,它对很多 Servlet API 提供了易用的代理方法,降低了访问 ...

  4. 动态规划-poj1949

    题目链接:http://poj.org/problem?id=1949 题目描述: 思路:用一个数组dp来存完成第i个任务时所需的最短的时间,dp[i] = max(dp[j]) +time, j是需 ...

  5. HDU-1009的解题报告

    Hdu-1009 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1009 题意:Fatmouse准备M磅的猫食,准备与猫守卫仓库有他最爱吃的食品贸易,J ...

  6. POJ 3258 River Hopscotch (最大最小距离)【二分】

    <题目链接> 题目大意:现在有起点和终点两个石块,这两个石块之间有N个石块,现在对这N个石块移除M个石块,使得这些石块之间的最短距离最大,注意,起点和终点这两个石块不能被移除. 解题分析: ...

  7. Java Lambda基础——Function, Consumer, Predicate, Supplier, 及FunctionalInterface接口

    这几个接口经常与Lambda结合使用,网上当然也有很多介绍,不过有些过于繁琐,有些又偏简单,秉着实用主义精神,今天这里折中一下,把介绍的内容分为两部分,第一部分相当于TLDR,总结几个"口诀 ...

  8. Linux开源监控平台归总

    Linux开源监控平台归总 Cacti 偏向于基础监控.成图非常漂亮,需要php环境支持,并且需要mysql作为数据存储 Cacti是一个性能广泛的图表和趋势分析工具,可以用来跟踪并几乎可以绘制出任何 ...

  9. XamarinAndroid组件教程设置动画的设置插值器

    XamarinAndroid组件教程设置动画的设置插值器 为动画设置插值器,可以使用BaseItemAnimator抽象类中的SetInterpolator()方法,其语法形式如下: public v ...

  10. sql的简单操作

    mysql 一.mysql简介和安装 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的关系型数据库管理系统,在 WEB 应 ...