Linux驱动程序中THIS_MODULE 的定义

结构体struct module在内核中代表一个内核模块,通过insmod(实际执行init_module系统调用)把自己编写的内核模块插入内核时,模块便与一个struct module结构体相关联,并成为内核的一部分。下面是结构体struct module的完整定义,接下来会逐个解释:


struct module

{

enum module_state state;

struct list_head list;

char name[MODULE_NAME_LEN];

struct module_kobject mkobj;

struct module_param_attrs *param_attrs;

const char *version;

const char *srcversion;

const struct kernel_symbol *syms;

unsigned int num_syms;

const unsigned long *crcs;

const struct kernel_symbol *gpl_syms;

unsigned int num_gpl_syms;

const unsigned long *gpl_crcs;

unsigned int num_exentries;

const struct exception_table_entry *extable;

int (*init)(void);

void *module_init;

void *module_core;

unsigned long init_size, core_size;

unsigned long init_text_size, core_text_size;

struct mod_arch_specific arch;

int unsafe;

int license_gplok;

#ifdef CONFIG_MODULE_UNLOAD

struct module_ref ref[NR_CPUS];

struct list_head modules_which_use_me;

struct task_struct *waiter;

void (*exit)(void);

#endif

#ifdef CONFIG_KALLSYMS

Elf_Sym *symtab;

unsigned long num_symtab;

char *strtab;

struct module_sect_attrs *sect_attrs;

#endif

void *percpu;

char *args;

};

我们插入一个内核模块,一般会使用工具insmod,该工具实际上调用了系统调用init_module,在该系统调用函数中,首先调用load_module,把用户空间传入的整个内核模块文件创建成一个内核模块,返回一个struct module结构体。内核中便以这个结构体代表这个内核模块。

  state是模块当前的状态。它是一个枚举型变量,可取的值为:MODULE_STATE_LIVE,MODULE_STATE_COMING,MODULE_STATE_GOING。分别表示模块当前正常使用中(存活状态),模块当前正在被加载,模块当前正在被卸载。load_module函数中完成模块的部分创建工作后,把状态置为MODULE_STATE_COMING,sys_init_module函数中完成模块的全部初始化工作后(包括把模块加入全局的模块列表,调用模块本身的初始化函数),把模块状态置为MODULE_STATE_LIVE,最后,使用rmmod工具卸载模块时,会调用系统调用delete_module,会把模块的状态置为MODULE_STATE_GOING。这是模块内部维护的一个状态。

  list是作为一个列表的成员,所有的内核模块都被维护在一个全局链表中,链表头是一个全局变量struct module *modules。任何一个新创建的模块,都会被加入到这个链表的头部,通过modules->next即可引用到。

  name是模块的名字,一般会拿模块文件的文件名作为模块名。它是这个模块的一个标识。

  另外,还要介绍一下宏THIS_MODULE,它的定义如下是#define THIS_MODULE (&__this_module),__this_module是一个struct module变量,代表当前模块,跟current有几分相似。可以通过THIS_MODULE宏来引用模块的struct module结构,试试下面的模块:


#include <linux/module.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)

{

unsigned int cpu = get_cpu();

struct module *mod;

printk(KERN_ALERT "this module: %p==%p\n", &__this_module, THIS_MODULE );

printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state );

printk(KERN_ALERT "module name: %s\n", THIS_MODULE->name );

list_for_each_entry(mod, *(&THIS_MODULE->list.prev), list )

printk(KERN_ALERT "module name: %s\n", mod->name );

return 0;

}

static void hello_exit(void)

{

printk(KERN_ALERT "module state: %d\n", THIS_MODULE->state );

}

module_init(hello_init);

module_exit(hello_exit);

最新内容请见作者的GitHub页:http://qaseven.github.io/

时间: 2024-11-02 04:03:59

Linux驱动程序中THIS_MODULE 的定义的相关文章

Linux中THIS_MODULE宏定义详解

   一直都在耿耿于怀,这个THIS_MODULE到底是个什么玩意,linux内核中无处不在的东西.今天上网搜了一下,算是基本明白了.网上牛人写的已经比较详细,另外目前暂时没有时间往更深层次分析,所以直接贴过来得了... 转帖网址: http://blog.csdn.net/a954423389/archive/2010/12/27/6101369.aspx 源码位置: @ kernel/module.c @ include/linux/module.h   结构体struct module在内

深入解析Linux系统中的SELinux访问控制功能

  SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统.NSA是在Linux社区的帮助下开发了一种访问控制体系,在这种访问控制体系的限制下,进程只能访问那些在他的任务中所需要文件.SELinux 默认安装在 Fedora 和 Red Hat Enterprise Linux 上,也可以作为其他发行版上容易安装的包得到. SELinux 是 2.6 版本的 Linux 内核中提供的强制访问控制

《Android深度探索(卷1):HAL与驱动开发》——6.2节编写Linux驱动程序的步骤

6.2 编写Linux驱动程序的步骤Android深度探索(卷1):HAL与驱动开发Linux驱动程序与其他类型的Linux程序一样,也有自己的规则.对于刚开始接触Linux驱动开发的读者可能对如何开发一个Linux驱动程序还不是太了解.为了解决这部分读者的困惑,本节给出了编写一个基本的Linux驱动的一般步骤.读者可以按照这些步骤循序渐进地学习Linux驱动开发. 第1步:建立Linux驱动骨架(装载和卸载Linux驱动) 任何类型的程序都有一个基本的结构,例如,C语言需要有一个入口函数mai

linux系统中定义的信号

linux系统中定义得信号可以通过kill -l命令查看,共定义了64个信号. Signal Description SIGABRT 由调用abort函数产生,进程非正常退出 SIGALRM 用alarm函数设置的timer超时或setitimer函数设置的interval timer超时 SIGBUS 某种特定的硬件异常,通常由内存访问引起 SIGCANCEL 由Solaris Thread Library内部使用,通常不会使用 SIGCHLD 进程Terminate或Stop的时候,SIGC

经典]Linux内核中ioremap映射的透彻理解【转】

转自:http://blog.csdn.net/lanyang123456/article/details/7403514 几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器.状态寄存器和数据寄存器三大类,外设的寄存器通常被连续地编址.根据CPU体系结构的不同,CPU对IO端口的编址方式有两种: (1)I/O映射方式(I/O-mapped) 典型地,如X86处理器为外设专门实现了一个单独的地址空间,称为"I/O地址空间"或者"I/O端口空间",CP

Linux驱动中completion接口浅析(wait_for_complete例子,很好)【转】

转自:http://blog.csdn.net/batoom/article/details/6298267  completion是一种轻量级的机制,它允许一个线程告诉另一个线程工作已经完成.可以利用下面的宏静态创建completion:                         DECLARE_COMPLETION(my_completion);                 如果运行时创建completion,则必须采用以下方法动态创建和初始化:                  

如何从失败的Linux引导中恢复

大多数 Linux 计算机使用 Grand Unified Bootloader (GRUB) - 更具体的讲是 GRUB 2 - 来控制从计算机的固件到内核的转移.GRUB 2 提供了复杂的引导时用户交互功能,为您提供了控制引导过程的能力.您可能不想每天都使用这些功能,但它们在处理问题的时候很重要,比如计算机在执行内核升级.磁盘更换或其他系统更改后无法引导的时候.一些技巧和 GRUB 命令可帮助您在这些情形下引导计算机,节省宝贵的时间.您也可以使用紧急引导磁盘引导您正常的 Linux 系统,即

linux内核 访问外设-Linux驱动中访问外设端口的outb为什么不是访问内存空间

问题描述 Linux驱动中访问外设端口的outb为什么不是访问内存空间 原文如下面,其中第一个宏的意思不是把值v赋给了内存地址为a的内存空间吗,为什么是访问outb是往外设端口写数据的? 在linux的驱动程序中,都会使用大量的outb.outw.inb.inw等等宏来访问硬件或寄存器.这些宏的定义都在相应处理器体系下的include/asm目录下的io.h中定义.追究下去,这些宏最终就是一个volatile变量的的赋值: #define arch_putb(v,a) (*(volatile u

《Android深度探索(卷1):HAL与驱动开发》——6.5节使用Eclipse开发和测试Linux驱动程序

6.5 使用Eclipse开发和测试Linux驱动程序 Android深度探索(卷1):HAL与驱动开发 在前面几节开发的word_count驱动和测试程序大多都需要在Linux终端进行编译(Android应用程序除外)和运行,而且也无法跟踪到Linux内核函数.变量.宏的内部(除非自己到Linux内核源代码中就寻找这些源代码文件),这并不利于深入了解Linux内核技术.在本节将为读者展示如何在Eclipse中开发Linux驱动程序,并且可以像跟踪Java代码一样直接跟踪到Linux内核源代码.