chishanmingshen 发表于 2013-01-24 19:06

关于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;
}

stephen_du 发表于 2013-01-24 19:06

stephen_du 发表于 2013-01-25 10:11

chishanmingshen 发表于 2013-01-25 10:26

感谢回复!
就是这个"unpack_to_rootfs就是将initramfs或者initrd的内容释放到"/"那里", 我搞不明白其中的奥秘...
是说释放之后, "/"就是实际根文件系统了, 是吧? 只是这个系统是特殊的, 是在ram中的?

回复 2# stephen_du


   

chishanmingshen 发表于 2013-01-25 13:03

哦...有点明白了.我的理解, 按顺序的3个阶段:
1. 首先建立虚拟根文件系统, 就是"/"
2. initrd/initramfs释放得到rootfs, 就是"/root"
3. mount真正的根文件系统, 自然也会有新的"/root"

如有不正, 请指点, 谢谢!

回复 4# stephen_du


   

stephen_du 发表于 2013-01-25 13:08

chishanmingshen 发表于 2013-01-25 15:08

最后一点:
header_buf symlink_buf name_buf : 这几个全局变量的作用是?

wangcong02345 发表于 2014-05-22 14:29

要知道 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:15

本帖最后由 chishanmingshen 于 2014-05-24 13:42 编辑

回复 8# wangcong02345

thanks!

>第一次解压usr/initramfs_data.cpio,这时候head_buff压根就没有用到.

第一次为啥没用到?请指教,谢谢!

wangcong02345 发表于 2014-05-26 11:33

head_buff什么时候才会用到呢? 只有在解压过程中才有可能用到.
像initramfs或者旧的initrd文件的生成过程都经过了gzip压缩,所以内核在用这些文件时需要先解压缩,gunzip每次会解压出32Kbuffer, 只有当这32k剩下的数据是cpio的头且不足110个字节时,才会用到header_buf.
而第一次解压的/usr/initramfs_dat.cpio,这是个cpio文件没有经过压缩,也就没有解压的过程,所以不会用到header_buf.
页: [1] 2
查看完整版本: 关于unpack_to_rootfs()的疑问