字符设备驱动框架

应用程序通过标准接口(C Library)调用驱动程序。

C Library 通过 swi 指令进入内核。

 

字符设备的注册

int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)

a、函数说明:

Param1:主设备号

Param2:设备名字

Param3:文件操作结构体指针

Return:当传入的主设备号为0时(系统自动分配主设备号),函数返回值为系统自动分配的主设备号

b、这个函数在内核中最简单的实现方式:

猜想:在内核里,声明一个struct file_operations类型的chrdev的数组,以major为下标;

当调用这个函数时,在指定下标的数组成员内,填充file_operations结构,实现驱动设备的注册。

   

驱动的使用方法

动态加载驱动的方法:

insmod *.ko

   

手动创建设备节点:

mknod /dev/xxx c 111 0

 

应用程序怎么操作底层设备呢?

fd = open("/dev/xxx", O_RDWR);

write(fd, &val, 4);

通过文件描述符,实现对底层设备的操作

   

如何自动创建设备节点?

mdev根据系统信息自动创建设备节点。

   

如何生成系统信息?

在加载驱动时生成,在入口函数实现。

   

为什么系统可以根据系统的设备信息动态生成/删除设备节点?

/etc/init.d/rcS 脚本文件,有如下内容:

echo /sbin/mdev > /proc/sys/kernel/hotplug

   

系统设备信息:

/sys/class/class_dev

class目录下,每一个class_dev存储一个设备驱动信息,mdev根据这个信息生成设备节点。

   

实际上,

对于驱动程序:(主设备号)

①由系统自动分配主设备号

②由用户指定主设备号

对于应用程序:(设备节点)

①手动创建设备节点

②由系统自动创建/删除设备节点

   

六、驱动程序基本框架

①实现驱动程序;

②声明并初始化file_operations结构体;(把驱动程序的函数指针填充到结构体中)

③编写入口函数,并在入口函数中注册设备驱动(register_chrdev(0, "drv_name", drv_fops););

④编写出口函数,并在出口函数中卸载驱动(unregister_chrdev(major, "drv_name"););

⑤修饰入口函数(module_init("入口函数"););

⑥修饰出口函数(module_exit("出口函数"););

   

七、实例

driver.c

1 #include <linux/module.h>
2 #include <linux/kernel.h>
3 #include <linux/fs.h>
4 #include <linux/init.h>
5 #include <linux/delay.h>
6 #include <asm/uaccess.h>
7 #include <asm/irq.h>
8 #include <asm/io.h>
9 #include <asm/arch/regs-gpio.h>
10 #include <asm/hardware.h>
11
12 int major;
13 static struct class *simple_class;
14 static struct class_device *simple_class_dev;
15
16 static int simple_open(struct inode *inode, struct file *file);
17 static ssize_t simple_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos);
18

19 static struct file_operations simple_fops = {
20         .open = simple_open,
21         .write = simple_write,
22         .owner = THIS_MODULE,
23 };
24
25 static int simple_open(struct inode *inode, struct file *file)
26 {
27         printk("simple_open ");
28         return 0;
29 }
30
31
32 static ssize_t simple_write(struct file *file, const char __user *buf,
33
size_t count, loff_t *ppos)
34 {
35         printk("simple_write ");
36         return 0;
37 }
38
39 static int __init simple_init(void)
40 {
41         major = register_chrdev(0, "simple", &simple_fops);
42         simple_class = class_create(THIS_MODULE, "myDrv");
43         simple_class_dev = class_device_create(simple_class, NULL, MKDEV(major, 0), NULL, "simple");
44         
45         return 0;
46 }
47
48 static void __exit simple_exit(void)
49 {
50         unregister_chrdev(major, "simple");
51         class_device_unregister(simple_class_dev);
52         class_destroy(simple_class);
53         return;
54 }
55
56 module_init(simple_init);
57 module_exit(simple_exit);
58
59 MODULE_LICENSE("GPL");

   

app.c

1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5
6 int main (void)
7 {
8         int fd;
9         int val = 1;
10         
11         printf("test app: ");
12         
13         fd = open("/dev/simple", O_RDWR);
14         if(fd < 0)
15         {
16                 printf("open failed!---%d--- ", fd);
17                 return 0;
18         }
19         write(fd, &val, 4);
20         
21         return 0;        
22 }

 

Makefile

1 KERN_DIR = /work/system/linux-2.6.22.6
2
3 all:
4         make -C $(KERN_DIR) M=`pwd` modules
5

6 clean:
7         make -C $(
KERN_DIR) M=`pwd` modules clean
8         
rm -rf modules.order

9
10 obj-m += simple.o

 

 

   

原文地址:https://www.cnblogs.com/lilto/p/11878237.html