zoukankan      html  css  js  c++  java
  • module_init宏解析 linux驱动的入口函数module_init的加载和释放

    linux驱动的入口函数module_init的加载和释放

    http://blog.csdn.net/zhandoushi1982/article/details/4927579

    void free_initmem(void)
    {
        if (!machine_is_integrator() && !machine_is_cintegrator()) {
        free_area((unsigned long)(&__init_begin),
         (unsigned long)(&__init_end),
         "init");
         }
    }
    

    http://www.cnblogs.com/super-king/p/3286766.html

    在init.h中我们看到
    #define module_init(x)  __initcall(x);
    还看到
    #define __initcall(fn) device_initcall(fn)
    还有
    #define __define_initcall(level,fn) 
        static initcall_t __initcall_##fn __attribute_used__ 
    __attribute__((__section__(".initcall" level ".init"))) = fn
    
    __define_initcall 作用
    
    宏定义__define_initcall(level,fn) 对于内核的初始化很重要,它指示编译器在编译的时候,将一系列初始化函数的起始地址值按照一定的顺序放在一个section中。在内核初始化阶 段,do_initcalls() 将按顺序从该section中以函数指针的形式取出这些函数的起始地址,来依次完成相应的初始化。由于内核某些部分的初始化需要依赖于其他某些部分的初始 化的完成,因此这个顺序排列常常非常重要。
    下面将从__define_initcall(level,fn) 宏定义的代码分析入手,依次分析名称为initcall.init的section的结构,最后分析内核初始化函数 do_initcalls()是如何利用宏定义__define_initcall(level,fn)及其相关的衍生的7个宏宏定义,来实现内核某些部分的顺序初始化的。
    1、分析 __define_initcall(level,fn) 宏定义
    1) 这个宏的定义位于inlcludelinuxinit.h中:
    #define __define_initcall(level,fn)   
        static initcall_t __initcall_##fn  
    __attribute__((__section__(".initcall" level ".init"))) 
    = fn
    其中 initcall_t 是一个函数指针类型:
    typedef int (*initcall_t)(void);
    而属性 __attribute__((__section__())) 则表示把对象放在一个这个由括号中的名称所指代的section中。
    所以这个宏定义的的含义是:
    
    (1) 声明一个名称为__initcall_##fn的函数指针(其中##表示替换连接);
    (2) 将这个函数指针初始化为fn;
    (3) 编译的时候需要把这个函数指针变量放置到名称为 ".initcall" level ".init"的section中(比如level="1",代表这个section的名称是 ".initcall1.init")。
    
    2) 举例:__define_initcall(6, pci_init)上述宏调用的含义是:
    
    声明一个函数指针__initcall_pic_init = pci_init;且
    这个指针变量__initcall_pic_init 需要放置到名称为 .initcall6.init的section中( 其实质就是将 这个函数pic_init的首地址放置到了这个section中)。
    
    3) 这个宏一般并不直接使用,而是被定义成下述其他更简单的7个衍生宏这些衍生宏宏的定义也位于 inlcludelinuxInit.h 中:
    
    #define core_initcall(fn)         __define_initcall("1",fn)
    #define postcore_initcall(fn)     __define_initcall("2",fn)
    #define arch_initcall(fn)         __define_initcall("3",fn)
    #define subsys_initcall(fn)       __define_initcall("4",fn)
    #define fs_initcall(fn)           __define_initcall("5",fn)
    #define device_initcall(fn)       __define_initcall("6",fn)
    #define late_initcall(fn)         __define_initcall("7",fn)
    因此通过宏 core_initcall() 来声明的函数指针,将放置到名称为
    .initcall1.init的section中,而通过宏 postcore_initcall() 来声明的函数指针,将放置到名称为.initcall2.init的section中,依次类推。
    
    4) 举例:device_initcall(pci_init)
    
    解释同上 1-2)。
    
    2、与初始化调用有关section--initcall.init被分成了7个子section
    
        1) 它们依次是.initcall1.init、.initcall2.init、...、.initcall7.init
        2) 按照先后顺序依次排列
        3) 它们的定义在文件vmlinux.lds.S中
        例如 对于i386+,在i386kernelvmlinux.lds.S中有:
        __initcall_start = .;
        .initcall.init : {
            *(.initcall1.init)
                *(.initcall2.init)
                *(.initcall3.init)
                *(.initcall4.init)
                *(.initcall5.init)
                *(.initcall6.init)
                *(.initcall7.init)
        }
    __initcall_end = .;
    而在makefile 中有
    
    LDFLAGS_vmlinux += -T arch/$(ARCH)/kernel/vmlinux.lds.s
    4) 在这7个section总的开始位置被标识为__initcall_start,而在结尾被标识为__initcall_end。
    
    3、 内核初始化函数do_basic_setup(): do_initcalls() 将从.initcall.init
        中,也就是这7个section中依次取出所有的函数指针,并调用这些函数指针所指向的函数,来完成内核的一些相关的初始化。
    这个函数的定义位于initmain.c中:
    //很简单
    static void __init do_initcalls(void)
    {
        ......
        for (call = __initcall_start; call < __initcall_end; call++) {
            ......
            result = (*call)();
            ......
            }
        ......
    }
    
  • 相关阅读:
    Swift学习笔记(7)--控制流
    安装APK时报 Installation failed with message Failed to finalize session : INSTALL_FAILED_USER_RESTRICTED: Invalid apk.
    Android Notification 的四种使用方式
    Socket.io
    socket
    socket.io 中文手册 socket.io 中文文档
    Android中的CardView使用
    TabLayout实现底部导航栏(2)
    使用PagerSlidingTabStrip实现顶部导航栏
    TabLayout实现顶部导航栏(1)
  • 原文地址:https://www.cnblogs.com/jingzhishen/p/4362578.html
Copyright © 2011-2022 走看看