赞
踩
app: open , read , write
驱动: led_open,led_read,led_write
驱动框架:
一、写出:led_open,led_read
二、怎么告诉内核?
a、定义一个file_operations
b、把这个结构体告诉内核:
register_chrdev(major,name,file_operations)
c、谁来调用它 (register_chrdev)
驱动的入口函数 first_drv_init
d、修饰:module_init(first_drv_init) (怎么知道是哪个入口函数)
module_init:(入口函数)定义了一个结构体,结构体有个函数指针,指向入口函数xxx_init。加载一个驱动的时候,内核就会找到这个结构体里面的函数指针,指向入口函数。
加载一个驱动时,内核就会找到这个结构体里面的函数指针,指向入口函数。入口函数把file_operations告诉内核。
介绍一个内核里的数组chrdevs(字符设备的file_operations和major都包含在这个数组中):
- static struct char_device_struct {
- struct char_device_struct *next;
- unsigned int major;
- unsigned int baseminor;
- int minorct;
- char name[64];
- struct file_operations *fops;
- struct cdev *cdev; /* will die */
- } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];
app:open("/dev/xxx")
打开文件的属性:c _ _ _, _ _ _, _ _ _, major, minor
设备类型,主设备号
内核数组chrdevs:
1 | 2 | …… | …… | …… | …… | major | …… | …… | …… |
★★VFS系统根据打开的这个文件的属性(设备类型:字符设备,主设备号major),就会找到注册进去的file_operations结构。
★★register_chrdev的实现:在一个内核数组chrdevs里,以major为索引,找到一项,在这一项里把file_operations填充进去,挂进去。
总结:
怎么根据打开的设备(open),找到驱动程序具体的实现(led_open)?
在内核定义了一个chrdevs数组,在这个数组里面,根据主设备号,找到了那一项的file_operations,这个file_operations结构是驱动程序里面实现的。
驱动程序:1、定义了led_open、led_write、led_read
2、定义了file_operations结构体,.open=led_open,.write=led_write
3、入口函数里,用register_chrdev(major,name,file_operations)把这个结构体放到内核数组chrdevs,对应的主设备号里面。
入口函数(注册):把file_operations结构体挂到chrdevs数组对应的设备号那一项
出口函数(卸载):把file_operations结构体从对应的设备号那一项拖出来。
第一个驱动程序 first_drv.c:
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/fs.h>
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <asm/uaccess.h>
- #include <asm/irq.h>
- #include <asm/io.h>
- #include <asm/arch/regs-gpio.h>
- #include <asm/hardware.h>
-
-
- static int first_drv_open(struct inode *inode, struct file *file)
- {
- printk("first_drv_open\n");
- return 0;
- }
-
- static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
- {
- printk("first_drv_write\n");
- return 0;
- }
-
- static struct file_operations first_drv_fops = {
- .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
- .open = first_drv_open,
- .write = first_drv_write,
- };
-
- int first_drv_init(void)
- {
- register_chrdev(111, "first_drv", &first_drv_fops); //注册驱动程序,告诉内核
- return 0;
- }
-
- void first_drv_exit(void)
- {
- unregister_chrdev(111, "first_drv"); //卸载驱动
- }
-
-
- module_init(first_drv_init);
- module_exit(first_drv_exit);
Makefile文件:
KERN_DIR = /work/system/linux-2.6.22.6
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += first_drv.o
KERN_DIR表示内核的目录,编一个驱动程序,依赖于内核。
-C:转到这个KERN_DIR这个目录去,用这个目录的Makefile来进行编译。
M=:当前目录是什么。modules:目标。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。