rk3188--4.android用initrd文件系统启动流程
来源:互联网 发布:天天饮食软件 编辑:程序博客网 时间:2024/05/21 06:30
在init/intramfs.c中- static int __init populate_rootfs(void)
- {
- unpack_to_rootfs(__initramfs_start, __initramfs_size); //1. initramfs的解压
- if (initrd_start) {
- unpack_to_rootfs((char*)initrd_start, initrd_end- initrd_start);//2.initrd的解压
- free_initrd();
- }
- }
- rootfs_initcall(populate_rootfs); //这个相当于module_init在系统初始化时会调用
unpack_to_rootfs(__initramfs_start, __initramfs_size);
rootfs_initcall(populate_rootfs);
--> populate_rootfs
--> unpack_to_rootfs
在init/initramfs.c中
- static char * __init unpack_to_rootfs(char *buf, unsigned len)
- {
- int i;
- int written, res;
- decompress_fn decompress;
- const char*compress_name;
- static __initdata char msg_buf[64];
- header_buf = kmalloc(110, GFP_KERNEL);
- symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX)+ 1, GFP_KERNEL);
- name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
- state = Start;
- this_header = 0;
- message =NULL;
- while(!message&&len){
- loff_t saved_offset = this_header;
- //如果开头以字符'0'开始,说明这是cpio格式的ram disk,不用解压直接用复制
- if(*buf=='0'&&!(this_header& 3)){
- state = Start;
- written = write_buffer(buf,len);
- buf += written;
- len-= written;
- continue;
- }
- }
- dir_utime();
- kfree(name_buf);
- kfree(symlink_buf);
- kfree(header_buf);
- return message;
- }
/dev 目录
/dev/console 文件
/root 目录
- dir /dev 0755 0 0
- nod /dev/console 0600 0 0 c 5 1
- dir /root 0700 0 0
buf=__initramfs_start, len=__initramfs_size
- static int __init write_buffer(char *buf, unsigned len)
- {
- count =len;
- victim = buf;
- while(!actions[state]())
- ;
- return len- count;
- }
因为在initramfs.cpio的文件长度都为0,所以没有do_copy的过程
write_buffer
--> do_start
在init/initramfs.c中
- static int __init do_start(void)
- {
- //实际作用是将collect指针移动到打包的cpio每一个文件头处
- read_into(header_buf, 110, GotHeader);
- return 0;
- }
- static void __init read_into(char*buf, unsigned size, enum statenext)
- {
- if (count >= size){
- collected = victim;
- eat(size);
- state =next; //下一步要执行do_header
- }
- }
write_buffer
--> do_start
--> do_header
- static int __init do_header(void)
- {
- if (memcmp(collected,"070707", 6)==0){
- error("incorrect cpio method used: use -H newc option");
- return 1;
- }
- if (memcmp(collected,"070701", 6)){
- error("no cpio magic");
- return 1;
- }
- parse_header(collected); //从101个字节的头中解析出inod mode uid gid等
- next_header = this_header + N_ALIGN(name_len)+ body_len; //移到下一个文件的头处
- next_header = (next_header + 3) & ~3; //cpio的头部都是4字节对齐的
- state = SkipIt;
- if (name_len <= 0|| name_len> PATH_MAX)
- return 0;
- if (S_ISLNK(mode)){
- if(body_len > PATH_MAX)
- return 0;
- collect = collected = symlink_buf;
- remains = N_ALIGN(name_len)+ body_len;
- next_state = GotSymlink;
- state = Collect;
- return 0;
- }
- //注意下面这个 !body_len,目录的body_len为0设备文件的body_len也为0
- //所以这儿代表的是,所有非链接文件
- if (S_ISREG(mode)||!body_len)
- read_into(name_buf, N_ALIGN(name_len), GotName); //这个实际的作用是,将指针移动到下一个文件的头处
- return 0; //并将状态改为GotName,即要调用do_name
- }
1.3 do_name建立目录文件
write_buffer
--> do_start
--> do_header
--> do_name
进行到此处,系统中己存在/与/root两个目录(都是虚拟的),此时再把打包在cpio里面的文件解析到系统的相应位置上.
- static int __init do_name(void)
- {
- state = SkipIt;
- next_state = Reset;
- if (strcmp(collected,"TRAILER!!!")== 0){ //判断是不是结尾
- free_hash();
- return 0;
- }
- clean_path(collected, mode); //把原先有的路径去掉, 相当于rmdir /dev 或 rm /dev/console
- if (S_ISREG(mode)){
- int ml= maybe_link();
- if(ml >= 0){
- int openflags= O_WRONLY|O_CREAT;
- if(ml != 1)
- openflags |= O_TRUNC;
- wfd = sys_open(collected, openflags, mode); //如果是普通文件打开sys_open
- if(wfd >= 0){
- sys_fchown(wfd, uid, gid); //设置权限等
- sys_fchmod(wfd, mode);
- if(body_len)
- sys_ftruncate(wfd, body_len);
- vcollected = kstrdup(collected, GFP_KERNEL);
- state = CopyFile; //最后调用do_copy将文件内容复制过来
- }
- }
- } else if (S_ISDIR(mode)){ // 以/dev为例
- sys_mkdir(collected, mode); // 创建 /dev目录
- sys_chown(collected, uid, gid); // 设置所有者
- sys_chmod(collected, mode); // 设置权限
- dir_add(collected, mtime); // 更改/dev目录的mtime
- } else if (S_ISBLK(mode)|| S_ISCHR(mode)|| S_ISFIFO(mode)|| S_ISSOCK(mode)){
- if(maybe_link()== 0){ // 以/dev/console为例
- sys_mknod(collected, mode, rdev); // 创建 /dev/console结点
- sys_chown(collected, uid, gid); // 设置所有者
- sys_chmod(collected, mode); // 设置权限
- do_utime(collected, mtime); // 更改时间戳
- }
- }
- return 0;
- }
write_buffer
--> do_start
--> do_header
--> do_name
--> do_skip
- static int __init do_skip(void)
- {
- if (this_header + count < next_header) {
- dbmsg();
- eat(count);
- return 1;
- } else {
- dbmsg();
- eat(next_header- this_header);
- state = next_state;
- return 0;
- }
- }
write_buffer
--> do_start
--> do_header
--> do_name
--> do_skip
--> do_reset
- static int __init do_reset(void)
- {
- dbmsg();
- while(count&&*victim == '\0')
- eat(1);
- if (count &&(this_header & 3))
- error("broken padding");
- return 1;
- }
2.1 initrd的起始地址的获取
make menuconfig中
General setup --->
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
start_kernel
-->setup_arch
在arch/arm/kernel/setup.c中
- void __init setup_arch(char**cmdline_p)
- {
- struct machine_desc *mdesc;
- mdesc = setup_machine_fdt(__atags_pointer);
- if (!mdesc)
- mdesc = setup_machine_tags(machine_arch_type); //读取内核参数
- //uboot的参数: init=/init initrd=0x62000000,0x00130000
- //指定了initrd在内存的起始地址0x62000000,长度0x130000
- parse_early_param();
- arm_memblock_init(&meminfo, mdesc);//将物理地址转为虚地址
- }
-->setup_arch
--> arm_memblock_init
在arch/arm/mm/init.c中
- void __init arm_memblock_init(struct meminfo*mi, struct machine_desc*mdesc)
- {
- #ifdef CONFIG_BLK_DEV_INITRD
- if (phys_initrd_size) {
- memblock_reserve(phys_initrd_start, phys_initrd_size);
- initrd_start = __phys_to_virt(phys_initrd_start); //将物理地址0x62000000转为虚地址
- initrd_end = initrd_start + phys_initrd_size; //end地址+size=0x00130000
- }
- #endif
- }
其中initrd_start是uboot传入的参数0x62000000的虚地址
里面的内容是烧入板子的boot.img去掉头8字节与尾4个字节,即out/target/product/rk3188/ramdisk.img
注: boot.img的生成
目录out/target/product/rk30sdk/root存在
a.将root下的每个文件加上cpio头+每个文件的内容,打包成cpios格式
b. 将这个cpio文件用gzip压缩后写到文件ramdisk.img中
c. mkkrnlimg会对ramdisk.img加上8个字节的头标志,尾部加上4个字节
2.2 解压并释放initrd中的文件目录
rootfs_initcall(populate_rootfs);
--> populate_rootfs
--> unpack_to_rootfs
在init/initramfs.c中
- static char * __init unpack_to_rootfs(char *buf, unsigned len)
- {
- int i;
- int written, res;
- decompress_fn decompress;
- const char*compress_name;
- static __initdata char msg_buf[64];
- header_buf = kmalloc(110, GFP_KERNEL);
- symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX)+ 1, GFP_KERNEL);
- name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
- if (!header_buf || !symlink_buf ||!name_buf)
- panic("can't allocate buffers");
- state = Start;
- this_header = 0;
- message =NULL;
- while(!message&&len){
- loff_t saved_offset = this_header;
- if(*buf=='0'&&!(this_header& 3)){
- //不是cpio格式,zip压缩过的开头不为字符'0'
- continue;
- }
- this_header = 0;
- //以开头的0x1f, 0x8b判断是zip压缩的,找到gunzip
- decompress = decompress_method(buf,len,&compress_name);
- //调用压缩函数进行解压缩,解压后调用flush_buffer拷贝到各个目录
- decompress(buf,len,NULL, flush_buffer,NULL,&my_inptr,error);
- this_header = saved_offset + my_inptr;
- buf += my_inptr;
- len-= my_inptr;
- }
- dir_utime();
- kfree(name_buf);
- kfree(symlink_buf);
- kfree(header_buf);
- return message;
- }
do_header
do_name
do_copy
do_utime
do_skip
do_reset
这儿的wite_buffer,比initramfs的write_buffer多了一个do_copy的过程
因为initramfs中只有名,没有数据.initrd有数据,所以需要将数据复制过去.
- static int __init flush_buffer(void *bufv, unsigned len)
- {
- char *buf= (char*) bufv;
- int written;
- int origLen= len;
- if (message)
- return -1;
- while((written= write_buffer(buf,len))< len&&!message){
- char c = buf[written];
- if(c =='0'){
- buf += written;
- len-= written;
- state = Start;
- }else if(c == 0){
- buf += written;
- len-= written;
- state = Reset;
- }else
- error("junk in compressed archive");
- }
- return origLen;
- }
0 0
- rk3188--4.android用initrd文件系统启动流程
- rk3188--4.android用initrd文件系统启动流程
- rk3188--9.android camera数据流程分析
- linux文件系统启动流程
- Linux启动 grub 虚拟文件系统initrd详解(一)
- Linux启动 grub 虚拟文件系统initrd详解(二)
- Linux启动 grub 虚拟文件系统initrd详解(三)
- ubuntu文件系统和启动流程
- rk3188+android在ubuntu上用wifi实现adb调试
- 构建根文件系统-initrd
- initrd 挂载根文件系统
- linux文件系统启动流程、启动脚本
- Initrd 流程分析
- linux根文件系统与initrd
- linux根文件系统与initrd
- linux根文件系统与initrd
- linux根文件系统与initrd
- linux根文件系统与initrd
- ios之遍历字典
- Ubuntu14.04下Nvidia opencl例子的编译运行
- SDN相关组织之NFV(network function virtualization)
- Jdk用native2ascii命令做unicode编码转换
- Android Studio解决unspecified on project app resolves to an APK archive which is not supported
- rk3188--4.android用initrd文件系统启动流程
- C++中不能声明为虚函数的有哪些函数
- java基础-IO-字符流、字节流
- Java和Android中,代码块、static静态代码块的执行顺序
- notify和notifyAll的区别和相同
- 图像分割之(六)交叉视觉皮质模型(ICM)
- Spring4新特性:泛型限定式依赖注入
- 控件选择日期不能小于今天
- UITableView设置cell为不可选?