字符設備驅動框架


應用程序通過標准接口(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

 

 

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM