生成字元類裝置節點
阿新 • • 發佈:2019-01-13
函式class_create建立class類檔案
– 引數1:一般是THIS_MODULE
– 引數2:裝置名稱
– 建立一個裝置類,用於裝置節點檔案的建立
– 返回一個class結構體變數
• class結構體變數
– class是裝置驅動模型中通用的裝置類結構
– 在標頭檔案include/linux/device.h的280行
建立裝置class函式class_device_create
– 標頭檔案include/linux/device.h中
– 引數1:class結構體變數
– 引數2:父裝置NULL
– 引數3:dev_t裝置號
– 引數4:資料NULL
– 引數5:裝置節點名稱
• 釋放裝置class函式class_destroy
– 引數1:class
建立裝置節點函式device_create
– 標頭檔案include/linux/device.h中
– 引數1:裝置所屬於的類
– 引數2:裝置的父裝置,NULL
– 引數3:裝置號
– 引數4:裝置資料,NULL
– 引數4:裝置名稱
摧毀裝置節點函式device_destroy
– 引數1:裝置所屬於的類
– 引數2:裝置號
釋放記憶體函式kfree
– 引數1:資料指標
測試原始碼:
/*包含初始化巨集定義的標頭檔案,程式碼中的module_init和module_exit在此檔案中*/ #include <linux/init.h> /*包含初始化載入模組的標頭檔案,程式碼中的MODULE_LICENSE在此標頭檔案中*/ #include <linux/module.h> /*定義module_param module_param_array的標頭檔案*/ #include <linux/moduleparam.h> /*定義module_param module_param_array中perm的標頭檔案*/ #include <linux/stat.h> /*三個字元裝置函式*/ #include <linux/fs.h> /*MKDEV轉換裝置號資料型別的巨集定義*/ #include <linux/kdev_t.h> /*定義字元裝置的結構體*/ #include <linux/cdev.h> /*分配記憶體空間函式標頭檔案*/ #include <linux/slab.h> /*包含函式device_create 結構體class等標頭檔案*/ #include <linux/device.h> #define DEVICE_NAME "chardevnode" #define DEVICE_MINOR_NUM 2 #define DEV_MAJOR 0 #define DEV_MINOR 0 #define REGDEV_SIZE 3000 MODULE_LICENSE("Dual BSD/GPL"); /*宣告是開源的,沒有核心版本限制*/ MODULE_AUTHOR("SKYFALL"); /*宣告作者*/ int numdev_major = DEV_MAJOR; int numdev_minor = DEV_MINOR; /*輸入主裝置號*/ module_param(numdev_major,int,S_IRUSR); /*輸入次裝置號*/ module_param(numdev_minor,int,S_IRUSR); static struct class *myclass; struct reg_dev { char *data; unsigned long size; struct cdev cdev; }; struct reg_dev *my_devices; struct file_operations my_fops = { .owner = THIS_MODULE, }; /*設備註冊到系統*/ static void reg_init_cdev(struct reg_dev *dev,int index){ int err; int devno = MKDEV(numdev_major,numdev_minor+index); /*資料初始化*/ cdev_init(&dev->cdev,&my_fops); dev->cdev.owner = THIS_MODULE; dev->cdev.ops = &my_fops; /*註冊到系統*/ err = cdev_add(&dev->cdev,devno,1); if(err){ printk(KERN_EMERG "cdev_add %d is fail! %d\n",index,err); } else{ printk(KERN_EMERG "cdev_add %d is success!\n",numdev_minor+index); } } static int scdev_init(void) { int ret = 0,i; dev_t num_dev; printk("%s,%d\n",__func__,__LINE__); printk(KERN_EMERG "numdev_major is %d!\n",numdev_major); printk(KERN_EMERG "numdev_minor is %d!\n",numdev_minor); if(numdev_major){ num_dev = MKDEV(numdev_major,numdev_minor); ret = register_chrdev_region(num_dev,DEVICE_MINOR_NUM,DEVICE_NAME); } else{ /*動態註冊裝置號*/ ret = alloc_chrdev_region(&num_dev,numdev_minor,DEVICE_MINOR_NUM,DEVICE_NAME); /*獲得主裝置號*/ numdev_major = MAJOR(num_dev); printk(KERN_EMERG "adev_region req %d !\n",numdev_major); } if(ret<0){ printk(KERN_EMERG "register_chrdev_region req %d is failed!\n",numdev_major); } myclass = class_create(THIS_MODULE,DEVICE_NAME); my_devices = kmalloc(DEVICE_MINOR_NUM * sizeof(struct reg_dev),GFP_KERNEL); if(!my_devices){ ret = -ENOMEM; goto fail; } memset(my_devices,0,DEVICE_MINOR_NUM * sizeof(struct reg_dev)); printk("%s,%d\n",__func__,__LINE__); /*裝置初始化*/ for(i=0;i<DEVICE_MINOR_NUM;i++){ my_devices[i].data = kmalloc(REGDEV_SIZE,GFP_KERNEL); memset(my_devices[i].data,0,REGDEV_SIZE); /*設備註冊到系統*/ reg_init_cdev(&my_devices[i],i); /*建立裝置節點*/ device_create(myclass,NULL,MKDEV(numdev_major,numdev_minor+i),NULL,DEVICE_NAME"%d",i); } printk(KERN_EMERG "scdev_init!\n"); /*列印資訊,KERN_EMERG表示緊急資訊*/ return 0; fail: /*登出裝置號*/ unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM); printk(KERN_EMERG "kmalloc is fail!\n"); return ret; } static void scdev_exit(void) { int i; printk("%s,%d\n",__func__,__LINE__); printk(KERN_EMERG "scdev_exit!\n"); /*除去字元裝置*/ for(i=0;i<DEVICE_MINOR_NUM;i++){ cdev_del(&(my_devices[i].cdev)); /*摧毀裝置節點函式d*/ device_destroy(myclass,MKDEV(numdev_major,numdev_minor+i)); } /*釋放裝置class*/ class_destroy(myclass); /*釋放記憶體*/ kfree(my_devices); unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM); } module_init(scdev_init); /*初始化函式*/ module_exit(scdev_exit); /*解除安裝函式*/
編譯,載入模組
– 使用命令“ls /sys/class/”可以檢視到生成的class
– 使用命令“ls /dev”可以檢視到生成的兩個裝置節點
載入模組的時候還可以使用命令生成裝置節點命令
mknod dev/test0 c 249 0
mknod dev/test1 c 249 1