Linux驱动开发的基本框架
#define LED_MAJOR 200
#define LED_NAME "led"
static int led_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int led_release(struct inode *inode, struct file *filp)
{
return 0;
}
static ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
return 0;
}
static const struct file_operations led_fops{
.owner = THIS_MODULE,
.open = led_open,
.release = led_release,
.write = led_write,
};
static int __init led_init(void)
{
int retvalue = 0;
retvalue = register_chrdev(LED_MAJOR, LED_NAME, &led_fops);
if(retvalue < 0){
printk("register chrdev filed!rn");
return -EIO;
}
}
static int __exit led_exit(void)
{
int retvalue = 0;
unregister_chrdev(LED_MAJOR, LED_NAME);
printk("led_exit!rn");
}
/* 注册驱动的加载与卸载 */
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZGS");
这里涉及到了Linux的三大结构体:file、inode、file_operations;
inode:
Linux一切皆文件,在Linux中每创建一个文件就会在相应的文件系统创建一个inode与之对应;当第一次open时就会将inode在内存中产生一个备份,同一个文件被多次打开并不会产生多个inode,当所有被打开的文件都被close之后,inode在内存中的实例就会被释放。当我们创建一个设备文件时,也会在文件系统中创建一个inode,这个inode用来存储关于这个文件的静态信息,包括这个设备文件对应的设备号,文件的路径以及对应的驱动对象etc。驱动开发中一般不需要自己填。对于不同的文件类型,inode被填充的成员内容也会有所不同,以创建字符设备为例,我们知道,add_chrdev_region其实是把一个驱动对象和一个(一组)设备号联系到一起。而创建设备文件,其实是把设备文件和设备号联系到一起。至此,这三者就被绑定在一起了。这样,内核就有能力创建一个struct inode实例了。
file:
Linux内核会为每一个进程维护一个文件描述符表,这个表其实就是struct file[]的索引。open()的过程其实就是根据传入的路径填充好一个file结构并将其赋值到数组中并返回其索引。
file_operations:
Linux使用file_operations结构访问驱动程序的函数,这个结构的每一个成员的名字都对应着一个调用。第一个 file_operations 成员根本不是一个操作; 它是一个指向拥有这个结构的模块的指针.、 这个成员用来在它的操作还在被使用时阻止模块被卸载. 几乎所有时间中, 它被简单初始化为 THIS_MODULE, 一个在 <linux/module.h> 中定义的宏.这个宏比较复杂,在进行简单学习操作的时候,一般初始化为THIS_MODULE。
(参考于
Linux驱动程序三大结构:inode,file,file_operations_Linux编程_Linux公社-Linux系统门户网站
Linux 驱动学习笔记 - file_operations结构体详细分析_Linux编程_Linux公社-Linux系统门户网站
因该网站我不知道如何私信作者,所以如有侵权请私信我删)。