• modules


    内核模块可以使用两种方式加入进内核:
    1.使用insmod等命令动态加载到内核(obj-m);
    2.作为内核的一部分静态编译进内核(obj-y);
     
    在linux/init.h文件中
     
    typedef int (*initcall_t)(void);
    typedef void (*exitcall_t)(void);
     
    #ifndef MODULE
    //静态方式
    #define __define_initcall(level,fn,id)
        static initcall_t __initcall_##fn##id __used
        __attribute__((__section__(".initcall" level ".init"))) = fn
     
    //最终展开为:
    //static initcall_t __initcall_test_init6 __used __attribute__((__section__(".initcall"6".init"))) = test_init
    //即将初始化函数test_init的地址放在了.initcall6.init的section,内核在启动的时候按级别顺序调用__initcall_start处的函数
    //start_kernel()->rest_init()->kernel_init()->do_basic_setup()->do_initcalls()

    #define device_initcall(fn)     __define_initcall("6",fn,6)
    #define __initcall(fn) device_initcall(fn)
    #define module_init(x)  __initcall(x);

    #define __exitcall(fn)
        static exitcall_t __exitcall_##fn __exit_call = fn

    //module_exit在静态编译的时候没有意义,因为静态编译的驱动无法卸载
    #define module_exit(x)  __exitcall(x);

    #else
    //动态方式
    #define module_init(initfn)                
        static inline initcall_t __inittest(void)         //检查初始化函数的格式是否满足initcall_t类型,当函数格式不匹配时,编译会warnning
        { return initfn; }                 
        int init_module(void) __attribute__((alias(#initfn))); 
         //为init_module函数定义一个别名,即初始化函数的名字。
         //insmod时候,在系统内部会调用sys_init_module()去找到init_module函数的入口地址
      //用objdump -t xxx.ko 命令可以看出test_init函数名的地址与init_module函数的地址相同。
     
    //module_exit函数的作用也是检查函数格式和定义别名。
    #define module_exit(exitfn)                
        static inline exitcall_t __exittest(void)      
        { return exitfn; }                 
        void cleanup_module(void) __attribute__((alias(#exitfn)));
     
    linux/arch/arm/kernel/vmlinux.lds
    .init.data : {
       *(.init.data) *(.meminit.data) *(.init.rodata) . = ALIGN(8); __start_ftrace_events = .; *(_ftrace_events) __stop_ftrace_events = .; *(.meminit.rodata) . = ALIGN(3    2); __dtb_start = .; *(.dtb.init.rodata) __dtb_end = .;
       . = ALIGN(16); __setup_start = .; *(.init.setup) __setup_end = .;
       __initcall_start = .; *(.initcallearly.init) __initcall0_start = .; *(.initcall0.init) *(.initcall0s.init) __initcall1_start = .; *(.initcall1.init) *(.initcall1s    .init) __initcall2_start = .; *(.initcall2.init) *(.initcall2s.init) __initcall3_start = .; *(.initcall3.init) *(.initcall3s.init) __initcall4_start = .; *(.initcal    l4.init) *(.initcall4s.init) __initcall5_start = .; *(.initcall5.init) *(.initcall5s.init) __initcallrootfs_start = .; *(.initcallrootfs.init) *(.initcallrootfss.in    it) __initcall6_start = .; *(.initcall6.init) *(.initcall6s.init) __initcall7_start = .; *(.initcall7.init) *(.initcall7s.init) __initcall_end = .;
       __con_initcall_start = .; *(.con_initcall.init) __con_initcall_end = .;
       __security_initcall_start = .; *(.security_initcall.init) __security_initcall_end = .;
       . = ALIGN(4); __initramfs_start = .; *(.init.ramfs) . = ALIGN(8); *(.init.ramfs.info)
      }
     
    示例代码:
    #include <linux/module.h>
                  
    int test_init(void)
    {
        printk("test test init
    ");                                                 
                                             
        return 0;                                     
    }                                                               
     
    void test_exit(void)                                        
    {                                          
        printk("test test exit
    ");        
    }                    
                             
    module_init(test_init);                               
    module_exit(test_exit);
                                           
                           
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("frank");
    MODULE_VERSION("1.0");   
  • 相关阅读:
    为何要对URL进行编码
    关于GreenPlum的一些整理
    Greenplum入门——基础知识、安装、常用函数
    PyGreSQL入门,pg模块,pgdb模块
    MySQL Test Suite使用
    MySQL到Greenplum迁移分析
    Method overrides should not change parameter defaults
    Why use a public method in an internal class?
    Git Submodules vs Git Subtrees
    To Allow App through Windows Defender Firewall in Command Prompt
  • 原文地址:https://www.cnblogs.com/black-mamba/p/5032997.html
Copyright © 2020-2023  润新知