应用程序通过标准接口(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