关于unpack_to_rootfs()的疑问
本帖最后由 chishanmingshen 于 2013-01-25 09:30 编辑from 3.6.10
populate_rootfs()->unpack_to_rootfs() 做新的initramfs或者旧的initrd的文件拷贝操作。
1. 可是我不明白的是拷贝到哪里去?不用指定文件名字么?比如initrd方式(非cpio)时,内核会建好文件/initrd.image,然后写入。
2. 此时是实际根文件系统是哪里加载的?因为后续才会加载实际根文件系统.
3. header_buf symlink_buf name_buf : 这几个全局变量的作用是?
4. 请指点这个函数的具体机制.
谢谢!
static char * __init unpack_to_rootfs(char *buf, unsigned len)
{
int written, res;
decompress_fn decompress;
const char *compress_name;
static __initdata char msg_buf;
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)) {
state = Start;
written = write_buffer(buf, len);<---(*actions[])将数据写到哪里去了?求详解。。
buf += written;
len -= written;
continue;
}
if (!*buf) {
buf++;
len--;
this_header++;
continue;
}
this_header = 0;
decompress = decompress_method(buf, len, &compress_name);
if (decompress) {
res = decompress(buf, len, NULL, flush_buffer, NULL,
&my_inptr, error);
if (res)
error("decompressor failed");
} else if (compress_name) {
if (!message) {
snprintf(msg_buf, sizeof msg_buf,
"compression method %s not configured",
compress_name);
message = msg_buf;
}
} else
error("junk in compressed archive");
if (state != Reset)
error("junk in compressed archive");
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;
}
感谢回复!
就是这个"unpack_to_rootfs就是将initramfs或者initrd的内容释放到"/"那里", 我搞不明白其中的奥秘...
是说释放之后, "/"就是实际根文件系统了, 是吧? 只是这个系统是特殊的, 是在ram中的?
回复 2# stephen_du
哦...有点明白了.我的理解, 按顺序的3个阶段:
1. 首先建立虚拟根文件系统, 就是"/"
2. initrd/initramfs释放得到rootfs, 就是"/root"
3. mount真正的根文件系统, 自然也会有新的"/root"
如有不正, 请指点, 谢谢!
回复 4# stephen_du
最后一点:
header_buf symlink_buf name_buf : 这几个全局变量的作用是? 要知道 header_buf symlink_buf name_buf,这三个buf的作用需要对cpio的格式有所了解.
CPIO 的结构是这样的:
110字节的Head(6 + 8*13)
不定长的文件名(文件名的长度是olen)
结束字符 \0
文件的内容
.... //重复上面4个
最后的文件名是一个 TRAILER!!!
了解了cpio的格式之后就很容易知道:
1. header_buf就是一个文件在cpio中的head,共110个字节
header_buf = kmalloc(110, GFP_KERNEL);
2.symlink_buf就是符号链接所指的路径
假设有这样的符号连接:ln -s /home/cong/Desktop/record.txt link
symlink_buf="/home/cong/Desktop/record.txt"
3. name_buf 就是文件名(除符号链接之外的文件名),
可以是普通文件名,目录名,FIFO名等反正就是存名字
这些都很容易理解, 就是有一点需要注意: 什么时候会用到这些buffer?
以header_buf为例说明一下:
内核两次调用了unpack_to_rootfs,
第一次解压usr/initramfs_data.cpio,这时候head_buff压根就没有用到.
第二次是解压initramfs,这个rootfs是gzip压缩的,内核会一边解压缩initramfs一边把解压出来的文件填充到文件系统中.
解压后并不是每一次都把110个字节拷贝到header_buf中,这样没有必要
而是在gunzip中每次解压出的32K的buffer, 只有当这32k剩下的数据是cpio的头且不足110个字节时,才会用到header_buf.
先将不足的字节临时放在header_buf中,然后再调用gunzip,从解出32K的buffer中拿走剩下的字节填充到header_buf中凑満110个字节.
symlink_buf, name_buf同样也是这种情况下才使用. 本帖最后由 chishanmingshen 于 2014-05-24 13:42 编辑
回复 8# wangcong02345
thanks!
>第一次解压usr/initramfs_data.cpio,这时候head_buff压根就没有用到.
第一次为啥没用到?请指教,谢谢! head_buff什么时候才会用到呢? 只有在解压过程中才有可能用到.
像initramfs或者旧的initrd文件的生成过程都经过了gzip压缩,所以内核在用这些文件时需要先解压缩,gunzip每次会解压出32Kbuffer, 只有当这32k剩下的数据是cpio的头且不足110个字节时,才会用到header_buf.
而第一次解压的/usr/initramfs_dat.cpio,这是个cpio文件没有经过压缩,也就没有解压的过程,所以不会用到header_buf.
页:
[1]
2