Linux kernel启动流程--Apple的学习笔记

今天看了下Kernel初始化流程,主要是了解顶层Makefile及lds连接文件,然后到初始化kernel内核及驱动,并且挂载根文件系统。

image.png

在kernel5.4.16中搜索__initcall_start,可以发现lds中定义了开始和结尾标识符,然后c语言中不定义,直接引用。而且这些start都放在了数组initcall_levels中。而这些数组被do_initcalls调用,先是for循环进行不同级别初始化,然后是同一级别的fn初始化。

数字越小,优先级越高。同一等级的优先级的驱动,加载顺序是链接过程决定的,结果是不确定的,我们无法去手动设置谁先谁后。

c代码中如下

#define pure_initcall(fn)       __define_initcall(fn, 0)

#define core_initcall(fn)       __define_initcall(fn, 1)
#define core_initcall_sync(fn)      __define_initcall(fn, 1s)
#define postcore_initcall(fn)       __define_initcall(fn, 2)
#define postcore_initcall_sync(fn)  __define_initcall(fn, 2s)
#define arch_initcall(fn)       __define_initcall(fn, 3)
#define arch_initcall_sync(fn)      __define_initcall(fn, 3s)
#define subsys_initcall(fn)     __define_initcall(fn, 4)
#define subsys_initcall_sync(fn)    __define_initcall(fn, 4s)
#define fs_initcall(fn)         __define_initcall(fn, 5)
#define fs_initcall_sync(fn)        __define_initcall(fn, 5s)
#define rootfs_initcall(fn)     __define_initcall(fn, rootfs)
#define device_initcall(fn)     __define_initcall(fn, 6)
#define device_initcall_sync(fn)    __define_initcall(fn, 6s)
#define late_initcall(fn)       __define_initcall(fn, 7)
#define late_initcall_sync(fn)      __define_initcall(fn, 7s)

#define ___define_initcall(fn, id, __sec) \
    static initcall_t __initcall_##fn##id __used \
        __attribute__((__section__(#__sec ".init"))) = fn;
#endif

#define __define_initcall(fn, id) ___define_initcall(fn, id, .initcall##id)

lds文件中有定义

#define INIT_CALLS_LEVEL(level)                     \
        __initcall##level##_start = .;              \
        KEEP(*(.initcall##level##.init))            \
        KEEP(*(.initcall##level##s.init))           \

#define INIT_CALLS                          \
        __initcall_start = .;                   \
        KEEP(*(.initcallearly.init))                \
        INIT_CALLS_LEVEL(0)                 \
        INIT_CALLS_LEVEL(1)                 \
        INIT_CALLS_LEVEL(2)                 \
        INIT_CALLS_LEVEL(3)                 \
        INIT_CALLS_LEVEL(4)                 \
        INIT_CALLS_LEVEL(5)                 \
        INIT_CALLS_LEVEL(rootfs)                \
        INIT_CALLS_LEVEL(6)                 \
        INIT_CALLS_LEVEL(7)                 \
        __initcall_end = .;


    .init.rodata : {
        INIT_SETUP(16)
        INIT_CALLS
        CON_INITCALL
        INIT_RAM_FS
    }
static void __init do_initcalls(void)
{
    int level;

    for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
        do_initcall_level(level);
}

参考网址

1.https://blog.csdn.net/xiaoxiaozhu2010/article/details/17693237
2.https://blog.csdn.net/shafa00419/article/details/85234867
3.https://www.cnblogs.com/GyForever1004/p/10400276.html
4.https://blog.csdn.net/wangliang888888/article/details/80859263

你可能感兴趣的:(Linux kernel启动流程--Apple的学习笔记)