• Linux编程——内核模块


    在FiRa的Android底层实现中,其IEEE 802.15.4协议相关实现均作为内核模块实现,因此,本文简要介绍内核模块的相关定义,并节选相关FiRa实现内核模块的使用。

    1. Linux内核模块

    内核模块是Linux操作系统中比较独特的机制。模块本身不被编译进内核镜像,这就有效控制了内核的大小;模块一旦被加载,就和内核中的其他部分完全一样。

    Linux启动中在完成BIOS加载、读取MBR、BootLoader启动之后,会根据内核映像所在路径,解压缩操作,开始启动内核,调用start_kernel函数来启动一系列的初始化函数并初始化各种设备。

    内核启动之后,会运行相关初始化工作,启动相关启动项。
    然后根据/etc/modules.conf文件或/etc/modules.d目录下的文件来加载内核模块。

    常见的内核模块包括驱动程序、文件系统、网络协议栈、安全模块和系统调用等。

    1.1 内核的加载和卸载

    内核模块通过insmodmodprobe命令加载内核模块,相应的加载函数就会被内核执行,完成本模块的相关初始化工作。

    当通过rmmod命令卸载某模块时,模块的卸载函数会被自动执行,完成与模块加载函数相反的功能(如释放内存等)。
    module_init,在内核模块被内核加载时,会调用module_init中的函数,即内核模块的加载函数。
    module_exit,在内核模块被卸载时的卸载函数,卸载内核模块时调用。
    在内核代码中,模块相关函数示例如下:

    static int __init function_init(void)
    {}
    
    static void __exit function_cleanup(void)
    {
    
    }
    module_init(function_init);
    module_exit(function_cleanup);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    另外,对于内核模块而言,授权MODULE_LICENSE是必须的,用于指定内核模块的许可证,其他模块参数相对可选。常见的许可证包括:GPL、LGPL、BSD、MIT等。常见的内核模块参数还有:

    • MODULE_AUTHOR,指定内核模块的作者
    • MODULE_DESCRIPTION,内核模块的描述信息
    • MODULE_VERSION,内核模块的版本信息
    • MODULE_SUPPORTED_DEVICE,指定内核模块支持的设备。
    • MODULE_DEVICE_TABLE
    • MODULE_ALIAS

    对于USB、PCI等设备驱动程序,通常会创建一个MODULE_DEVICE_TABLE,表明该驱动模块支持的设备。

    符号导出EXPORT_SYMBOL

    • EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。
    • 在调用该函数的另外一个模块中使用extern对之声明。
    • 注意:先加载定义该函数的模块,然后再加载调用该函数的模块,请注意这个先后顺序,顺序不能错。

    示例——FiRa IEEE 802.15.4相关内核模块

    mcps_main

    int __init mcps802154_init(void)
    {
    	int r;
    
    	r = mcps802154_nl_init();
    	if (r)
    		return r;
    	r = mcps802154_default_region_init();
    	WARN_RETURN(r);
    	r = simple_ranging_region_init();
    	WARN_ON(r);
    	r = mcps802154_endless_scheduler_init();
    	WARN_ON(r);
    #ifdef CONFIG_MCPS802154_TESTMODE
    	r = ping_pong_region_init();
    	WARN_ON(r);
    #endif
    	return r;
    }
    
    void __exit mcps802154_exit(void)
    {
    #ifdef CONFIG_MCPS802154_TESTMODE
    	ping_pong_region_exit();
    #endif
    	mcps802154_endless_scheduler_exit();
    	simple_ranging_region_exit();
    	mcps802154_default_region_exit();
    	mcps802154_nl_exit();
    }
    
    module_init(mcps802154_init);
    module_exit(mcps802154_exit);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    FiRa域

    module_init(fira_region_init);
    module_exit(fira_region_exit);
    
    MODULE_DESCRIPTION("FiRa Region for IEEE 802.15.4 MCPS");
    MODULE_AUTHOR("Nicolas Schodet ");
    MODULE_VERSION("1.0");
    MODULE_LICENSE("GPL v2");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    FiRa调度器符号导出

    //MCPS, 调度器管理,实现调度器的注册与注销
    EXPORT_SYMBOL(mcps802154_scheduler_register);
    EXPORT_SYMBOL(mcps802154_scheduler_unregister);
    
    • 1
    • 2
    • 3
  • 相关阅读:
    基于HTTP服务器/客户端的实验
    BeanUtils.copyProperties的使用场景
    摄像头对人脸进行性别和年龄的判断
    C语言实现扫雷游戏(分解代码,超级详细,无压力)
    C++ 简易日志类封装
    IDEA远程一键部署SpringBoot到Docker
    Kotlin - 协程构建器 CoroutineBuilder
    代码随想录第43天|416. 分割等和子集,1049. 最后一块石头的重量 II, ​494.目标和,​ 474.一和零(一窍不通)
    2023年【金属非金属矿山(地下矿山)安全管理人员】实操考试视频及金属非金属矿山(地下矿山)安全管理人员操作证考试
    JavaScript对象详解,js对象属性的添加
  • 原文地址:https://blog.csdn.net/luo58614013/article/details/133514538