1. The root file system is stored in flash, and it will take a long time to start the device. This is because reading rootfs data from flash is time-consuming, and reading *. Stored in rootfs at the same time so,*. ko and other documents are also time-consuming. This is determined by the read and write properties of flash itself. For some devices that need to start quickly, the read-write rate of flash cannot be met, so you can consider mounting rootfs in memory, that is, ramdisk.
2. Using ramdisk requires kernel support, and config needs to be opened_ BLK_ DEV_ Initrd macro
3. The initramfs initialization flow chart is shown in the following figure, which is mainly divided into two parts.
3.1. Mount rootfs ("/"), vfs_caches_init branch
3.2. Making rootfs and rest_init branch
4. Establish rootfs
struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { ...... root = mount_fs(type, flags, name, data); ...... } EXPORT_SYMBOL_GPL(vfs_kern_mount);
According to VFS_ kern_ The name="rootfs" passed in by the mount function will eventually execute rootfs_mount completes the establishment of the root file system.
static struct file_system_type rootfs_fs_type = { .name = "rootfs", .mount = rootfs_mount, .kill_sb = kill_litter_super, };
5. Make root file system
5.1. How to start from__ initcall6_start to populate_rootfs
device_initcall(populate_rootfs);
populate_rootfs function through device_initcall macro, loaded into a specific section (. initcall6.init)
#define device_initcall(fn) __define_initcall(fn, 6) #define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id) #define ___define_initcall(fn, id, __sec) \ static initcall_t __initcall_##fn##id __used \ __attribute__((__section__(#__sec ".init"))) = fn;
device_initcall function__ initcall_populate_rootfs6 is stored in initcall6. In the section of init
Via / / include / ASM generic / vmlinux lds. H link script file, found
When executed__ initcall6_ When the start function is executed, it is stored in the initcall6.init is the data of this section, i.e__ initcall_populate_rootfs6 function
5.2. Making rootfs
static int __init populate_rootfs(void) { char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size); ...... if (initrd_start) { ...... printk(KERN_INFO "Unpacking initramfs...\n"); err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start); if (err) printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err); free_initrd(); /* * Try loading default modules from initramfs. This gives * us a chance to load before device_initcalls. */ load_default_modules(); } return 0; }
5.2.1 first unpcak_ to_ [_initramfs_start, _initramfs_start + _initramfs_size] data of rootfs
Via / / include / ASM generic / vmlinux lds. H link script file, found
It defines init.ramfs and init.ramfs.info two section s
Via / / usr/initramfs_data.S file discovery__ initramfs_size is determined by initramfs_data.o confirm
Including INITRAMFS_IMAGE is defined in / / usr/Makefile file
initramfs is generally not used after loading
5.2.2 post unpack_ to_ [initrd_start, initrd_end] data of rootfs
Where initrd_end and initrd_start is passed in through cmdline, and the data has been decompressed from the rootfs partition of flash and moved to initrd in the uboot phase_ Start address.
5.2.2.1 production of rootfs in flash image
rootfs generates *. Through cpio command cpio files are compressed according to the compression method (in the build\images.mk script)
#lzo compression mode, rootfs Bin is rootfs_initramfs.cpio lzo compressed file lzop -x rootfs.bin #Convert the cpio file into directory format, and ls view the specific directory content cpio -idmv < rootfs_initramfs.cpio
5.2.2.2 production of rootfs in memory
static char * __init unpack_to_rootfs(char *buf, unsigned len) { ...... while (!message && len) { loff_t saved_offset = this_header; if (*buf == '0' && !(this_header & 3)) { state = Start; written = write_buffer(buf, len); ...... } ...... 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"); } ...... } }
The data in the current buf has been decompress ed and written directly_ Buffer function production; No specific compression method is used to de compress the post flush_buffer implementation
write_buffer parses the buf fer data through the following functions to complete the creation of the root file system
static __initdata int (*actions[])(void) = { [Start] = do_start, [Collect] = do_collect, [GotHeader] = do_header, [SkipIt] = do_skip, [GotName] = do_name, [CopyFile] = do_copy, [GotSymlink] = do_symlink, [Reset] = do_reset, };
6. Run the application in the file system
//kernel_ In the init function, execute ramdisk_execute_command application, where ramdisk_execute_command passed in from cmdline if (ramdisk_execute_command) { if (!run_init_process(ramdisk_execute_command)) return 0; pr_err("Failed to execute %s\n", ramdisk_execute_command); }