struct file_operations *fops)
{
int err, devno = MKDEV(simple_major, minor);
cdev_init(dev, fops);
dev-》owner = THIS_MODULE;
err = cdev_add (dev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk (KERN_NOTICE “Error %d adding simple%d”, err, minor);
}
无论是cdev还是file_operations都将自己的struct module *owner成员指向了THIS_MODULE。那么这个THIS_MODULE 是什么呢?
内核源码目录下include/linux/module.h
#ifdef MODULE
#define MODULE_GENERIC_TABLE(gtype,name) /
extern const struct gtype##_id __mod_##gtype##_table /
__attribute__ ((unused, alias(__stringify(name))))
extern struct module __this_module;
#define THIS_MODULE (&__this_module)
#else /* !MODULE */
#define MODULE_GENERIC_TABLE(gtype,name)
#define THIS_MODULE ((struct module *)0)
#endif
__this_module这个符号是在加载到内核后才产生的。insmod命令执行后,会调用kernel/module.c里的一个系统调用 sys_init_module,它会调用load_module函数,将用户空间传入的整个内核模块文件创建成一个内核模块,并返回一个struct module结构体,从此,内核中便以这个结构体代表这个内核模块。THIS_MODULE类似进程的CURRENT。
struct module
{……
struct module_ref ref[NR_CPUS];
}
struct module_ref
{
local_t count;//记录模块使用计数
} ____cacheline_aligned;
现在咱们就看看内核是如何帮助我们完成使用计数的。
在2.4内核中,我们是通过在open方法中增加引用计数,在close方法中减少引用计数。在2.6内核中,内核肯定也是要在open、close时帮助我们实现同样功能的。
打开字符设备的大体流程如下:
sys_open()-》do_sys_open()-》do_filp_open()-》nameidata_to_filp() -》__dentry_open()-》chrdev_open()-》open()