ramdisk.img是編譯Android生成的一個鏡像文件亲善,最后和kernel一起打包生成boot.img鏡像辙喂。ramdisk.img中主要是存放android啟動后第一個用戶進程init可執(zhí)行文件和init.*.rc等相關啟動腳本以及sbin目錄下的adbd工具棺耍。
file ramdisk.img
//ramdisk.img: gzip compressed data, from Unix
看出為gzip壓縮過的文件,將ramdisk.img重命名為ramdisk.img.gz .
mv ramdisk.img ramdisk.img.gz
gunzip ramdisk.img.gz
file ramdisk.img
//ramdisk.img: ASCII cpio archive (SVR4 with no CRC)
cpio -i -F ramdisk.img
rootfs之所以存在镊屎,是因為需要在VFS機制下給系統(tǒng)提供最原始的掛載點。
1.initrd (init:initialized, rd:ramdisk)
在早期的linux系統(tǒng)中,一般只有硬盤或者軟盤被用來作為linux根文件系統(tǒng)的存儲設備,因此也就很容易把這些設備的驅(qū)動程序集成到內(nèi)核中明郭。但是現(xiàn)在的嵌入式系統(tǒng)中可能將根文件系統(tǒng)保存到各種存儲設備上,包括scsi丰泊、sata薯定,u-disk等等。因此把這些設備的驅(qū)動代碼全部編譯到內(nèi)核中顯然就不是很方便瞳购。
為了解決這一矛盾话侄,于是出現(xiàn)了基于ramdisk的initrd( bootloader initialized RAM disk )。Initrd是一個被壓縮過的小型根目錄,這個目錄中包含了啟動階段中必須的驅(qū)動模塊年堆,可執(zhí)行文件和啟動腳本吞杭。當系統(tǒng)啟動的時候,bootloader會把initrd文件讀到內(nèi)存中变丧,然后把initrd文件在內(nèi)存中的起始地址和大小傳遞給內(nèi)核
內(nèi)核在啟動初始化過程中會解壓縮initrd文件芽狗,然后將解壓后的initrd掛載為根目錄,
然后執(zhí)行根目錄中的/linuxrc腳本(cpio格式的initrd為/init,而image格式的initrd<也稱老式塊設備的initrd或傳統(tǒng)的文件鏡像格式的initrd>為/initrc)痒蓬,
2.Initramfs
initramfs童擎,它的作用和initrd類似,只是和內(nèi)核編譯成一個文件(該initramfs是經(jīng)過gzip壓縮后的cpio格式的數(shù)據(jù)文件)谊却,該cpio格式的文件被鏈接進了內(nèi)核中特殊的數(shù)據(jù)段.init.ramfs上
其中全局變量__initramfs_start和__initramfs_end分別指向這個數(shù)據(jù)段的起始地址和結束地址柔昼。內(nèi)核啟動時會對.init.ramfs段中的數(shù)據(jù)進行解壓,然后使用它作為臨時的根文件系統(tǒng)炎辨。
支持initrd的內(nèi)核配置(需要內(nèi)核支持內(nèi)存盤驅(qū)動):
General setup->Initial RAM filesystem and RAM disk(initramfs/initrd) support
RamDisk內(nèi)存盤驅(qū)動
Device Drivers->Block devices->RAM block device support
啟動參數(shù)
Boot options->Default kernel command string
填寫如下:mem=32M console=ttySAC0 root=/dev/ram initrd=0xc1000000,0x00600000 ramdisk_size=8192 rw
cpio
cpio 可以從 cpio 或 tar 格式的歸檔包中存入和讀取文件, 歸檔包是一種包含其他文件和有關信息的文件捕透。 有關信息包括:文件名, 屬主, 時標(timestamp), 和訪問權限。 歸檔包可以是磁盤上的 其他文件, 也可以是磁帶或管道碴萧。
cpio命令有三種操作模式:copy-out乙嘀、copy-in、copy-pass破喻,生成 ramdisk.img 用的是它的copy-out模式虎谢,即把文件打包的操作模式。cpio的copy-out操作模式使用 -o 命令行選項指定
cd ~/root
find . | cpio -o -Hnewc |gzip -9 > ../image.cpio.gz
rootfs 啟動過程
rootfs是ramfs或tmpfs的一種實例曹质,它不能被umount婴噩,對于內(nèi)核而言,rootfs體積小且簡單羽德,主要用于確保某些目錄不能為空几莽。
ramfs是一種非常簡單的RAM系統(tǒng),它基于linux系統(tǒng)硬盤緩沖機制宅静,可以動態(tài)改變大小章蚣。
__init start_kernel(void)
vfs_caches_init_early();
dcache_init_early();
inode_init_early();
--> vfs_caches_init(num_physpages);
dcache_init();
inode_init();
files_init(mempages);
--> mnt_init();
--> init_rootfs();
--> init_mount_tree();
以上代碼中,從start_kernel開始姨夹,初始化虛擬文件系統(tǒng)纤垂,包括dcache、inode初始磷账,創(chuàng)建內(nèi)核對象fs峭沦,然后開始初始化rootfs。
內(nèi)核掛載rootfs之后需要將ramdisk中的解壓到rootfs中逃糟,因此內(nèi)核必須知道ramdisk在內(nèi)存上的地址熙侍。已知有三種方式可以通知內(nèi)核ramdisk的位置。
1.通過cmdline傳入
2.bootloader 通過setup_initrd_tag函數(shù)把initrd_start設置到內(nèi)核 tag中,內(nèi)核通過parse_tag解析
init_mount_tree(void)
vfs_kern_mount(type, 0, "rootfs", NULL);
rootfs_mount(struct file_system_type *fs_type,
//內(nèi)核就把rootfs掛載起來了蛉抓,此時rootfs還是個空目錄庆尘,并且只有一個根目錄‘/’。
do_initcalls(void)
define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
populate_rootfs(void)
unpack_to_rootfs
//unpack_to_rootfs會先解壓ramdisk成一個cpio文件巷送,然后解析解析cpio文件中所有文件驶忌,并生成對應的文件到rootfs中
ramdisk的制作
out/host/linux-x86/bin/mkbootfs out/target/product//root | out/host/linux-x86/bin/minigzip > out/target/product//ramdisk.img
上述命令分兩步進行:
out/host/linux-x86/bin/mkbootfs out/target/product/*/root
生成一個cpio文件,利用cpio 可將文件或目錄從文件庫獲取出來或?qū)⑸⒘形募截惖轿募臁?/p>
out/host/linux-x86/bin/minigzip
將生成的cpio文件壓縮成一個gzip格式的文件“out/target/product/*/ramdisk.img“
mkbootfs
mkbootfs 生成ramdisk.img ( 源碼在system/core/cpio)
$(hide) $(MKBOOTFS) $(TARGET_ROOT_OUT) | $(MINIGZIP) > $@
mkbootimg
mkbootimg的源代碼在system/core/mkbootimg中笑跛。
mkbootimg --kernel kernel --ramdisk ramdisk.img --output /tmp/boot.img
minigzip
minigzip的源代碼在external/zlib中付魔。
fs_config
源碼位于:build/tools/fs_config。
其中的fs_config.c包含了system/core/include/private/android_filesystem_config.h飞蹂,真正權限配置和fs_config的實現(xiàn)都在這個頭文件中几苍。
signapk
signapk的源碼位于:build/tools/signapk。