#include <linux/module.h> #include <linux/fs.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/atomic.h> #include <linux/types.h> #include <linux/interrupt.h> #include <linux/kthread.h> #include <linux/slab.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/dma-mapping.h> //定義設備名稱為test-dev #define DEV_NAME "test-dev" //定義並初始化一個類 struct class cla = { .name = "test-cla", //將類的名字設置為test-cla .owner = THIS_MODULE, //該類的擁有者為這個模塊 }; int test_open(struct inode *node, struct file *filp) { printk("test open\n"); return 0; } int test_close(struct inode *node, struct file *filp) { printk("test close\n"); return 0; } //填充並初始化file_operations結構體 struct file_operations fops = { .owner = THIS_MODULE, .open = test_open, .release = test_close, }; //定義設備 struct device dev = { .init_name = DEV_NAME, .class = &cla, //設備歸類cla; .release = test_release, }; //定義主設備號和次設備號 int major = 0; int minor = 0; int test_init(void) { int ret; printk("test init\n"); //將類進行注冊 ret = class_register(&cla); //如果返回值不為0,返回錯誤值 if(IS_ERR_VALUE(ret)) { return ret; } //注冊一個字符設備驅動 ret = register_chrdev(major, DEV_NAME, &fops); //如果注冊不成功返回錯誤值並撤銷類的實現 if(IS_ERR_VALUE(ret)) { class_unregister(&cla); return ret; } major = ret; //printk("major = %d\n", major); //申請主設備號與次設備號 dev.devt = MKDEV(major, minor); //將設備進行注冊 ret = device_register(&dev); //如果設備注冊不成功,撤銷類設備注冊並解除字符設備驅動的注冊 if(IS_ERR_VALUE(ret)) { class_unregister(&cla); unregister_chrdev(major, DEV_NAME); return ret; } return 0; } void test_exit(void) { printk("test exit\n"); //解除字符設備的注冊 unregister_chrdev(major, DEV_NAME); //解決類設備注冊 device_unregister(&dev); class_unregister(&cla); } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("yangyx"); MODULE_VERSION("1.1");