首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

嵌入式驱动编程中结构体file_operations的第一个成员 struct module *owner 通常被赋值为 THIS_MODULE 这是怎么回事儿?【THIS_MODULE宏的详细介绍】

  • 25-03-05 04:42
  • 4249
  • 8866
blog.csdn.net

文件操作结构体file_operations的完整定义见博文 http://iyenn.com/rec/1709536.html

嵌入式驱动编程中结构体file_operations的第一个成员 struct module *owner 通常被赋值为 THIS_MODULE 这是怎么回事儿?

比如下面的代码:

static const struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open = led_open,
    .write = led_write,
};
  • 1
  • 2
  • 3
  • 4
  • 5

我们在Linux的源码中(include\linux\export.h)可以查到THIS_MODULE是一个宏定义,具体如下:

#ifdef MODULE
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
#else
#define THIS_MODULE ((struct module *)0)
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

把这段代码理解了,基本上就理解了,下面是详细讲解。

在 Linux 内核中,THIS_MODULE 是一个宏,用于指向当前驱动模块的 struct module 实例。它的作用是为模块提供元信息和生命周期管理支持。


THIS_MODULE 的定义解读

#ifdef MODULE
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
#else
#define THIS_MODULE ((struct module *)0)
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. MODULE 宏:

    • MODULE 是一个条件编译宏,当编译成模块(.ko 文件)时,编译器会定义 MODULE。
    • 如果模块被静态编译进内核(而不是动态加载的模块),MODULE 不会被定义。
  2. __this_module:

    • 如果 MODULE 被定义,THIS_MODULE 会展开为 &__this_module,即当前模块的 struct module 实例。
    • __this_module 是一个由内核自动生成的全局变量,包含模块的相关信息,如模块名、引用计数等。
  3. 静态内核情况:

    • 如果模块被静态编译进内核,MODULE 未定义,此时 THIS_MODULE 被设置为 NULL,因为静态内核中的模块不需要动态管理。

THIS_MODULE 在驱动中的用途

THIS_MODULE 被赋值给 struct file_operations 的 owner 成员,主要用于模块的引用计数管理:

static struct file_operations led_fops = {
    .owner = THIS_MODULE,
    .open  = led_open,
    .read  = led_read,
    .write = led_write,
    .release = led_release,
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 模块引用计数:

    • 当设备文件被打开时(调用 open 函数),内核会增加模块的引用计数,防止模块在使用过程中被卸载。
    • 当设备文件被关闭时(调用 release 函数),内核会减少引用计数。
  2. 避免非法卸载:

    • 如果模块的引用计数大于 0,rmmod 命令无法卸载该模块,从而防止非法卸载可能导致的系统崩溃。
  3. 动态模块管理:

    • 通过 THIS_MODULE,内核可以准确管理模块的生命周期,包括加载、使用和卸载。

struct module 的结构

struct module 定义在 中,主要包含以下信息:

struct module {
    const char *name;           // 模块名称
    struct list_head list;      // 模块链表
    struct module_kobject mkobj; // 模块的 kobject
    struct module_param_attrs *param_attrs; // 模块参数的 sysfs 接口
    struct list_head source_list; // 源文件相关信息
    unsigned int taints;        // 模块的 taints 标志
    struct mutex mutex;         // 模块互斥锁
    unsigned long state;        // 模块的状态
    ...
    unsigned int refcnt;        // 引用计数
    ...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • name: 模块名称。
  • refcnt: 引用计数,记录模块被使用的次数。
  • state: 模块状态,例如正在初始化、已加载等。

在动态加载和静态内核中的差异

  1. 动态加载模块:

    • 使用 THIS_MODULE,owner 会指向 &__this_module,从而实现引用计数管理。
  2. 静态编译进内核:

    • THIS_MODULE 为 NULL,因为静态模块不会被卸载,也不需要引用计数管理。

一个示例:模块的引用计数管理

假设一个设备驱动模块如下:

#include 
#include 
#include 

static int dev_open(struct inode *inode, struct file *file) {
    printk(KERN_INFO "Device opened\n");
    return 0;
}

static int dev_release(struct inode *inode, struct file *file) {
    printk(KERN_INFO "Device released\n");
    return 0;
}

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = dev_open,
    .release = dev_release,
};

static int __init mod_init(void) {
    int major = register_chrdev(0, "my_device", &fops);
    printk(KERN_INFO "Module loaded, major number %d\n", major);
    return 0;
}

static void __exit mod_exit(void) {
    unregister_chrdev(0, "my_device");
    printk(KERN_INFO "Module unloaded\n");
}

module_init(mod_init);
module_exit(mod_exit);

MODULE_LICENSE("GPL");
  • 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
  • 34
  • 35
  1. 当设备文件 /dev/my_device 被打开时:

    • 内核通过 THIS_MODULE 增加引用计数,防止模块被卸载。
    • 调用 dev_open 函数。
  2. 当设备文件被关闭时:

    • 内核通过 THIS_MODULE 减少引用计数。
    • 调用 dev_release 函数。

总结

THIS_MODULE 是一个宏,用于引用当前模块的 struct module 实例【注意:当前模块的 struct module 的实例是由系统自动生成的】,主要作用是管理模块的引用计数,防止模块在使用过程中被非法卸载。它的工作机制依赖于内核的模块管理框架,与设备驱动的生命周期紧密相关。

由于我们编写的驱动程序本质上也是一个模块,所以我们需要用到宏THIS_MODULE 。

昊虹嵌入式技术交流群
QQ群名片
注:本文转载自blog.csdn.net的昊虹AI笔记的文章"https://blog.csdn.net/wenhao_ir/article/details/144906774"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top