應用程序通過標准接口(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\n");
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\n");
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:\n");
12
13 fd = open("/dev/simple", O_RDWR);
14 if(fd < 0)
15 {
16 printf("open failed!---%d---\n", 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