前面學習的雜項設備,主設備號已經固定爲 10,這裏介紹申請標準的字符類設備號,包括主設備號以及次設備號。
字符類設備號分爲靜態申請和動態申請,靜態申請就是主設備號是程序員手動分配,動態申請是系統給分配。
字符設備函數在文件“include/linux/fs.h”中。
內核提供了三個函數來註冊一組字符設備編號,這三個函數分別是:
– register_chrdev_region(); //靜態申請
– alloc_chrdev_region(); //動態申請
– register_chrdev()。
register_chrdev_region()是提前知道設備的主次設備號,再去申請設備號。alloc_chrdev_region() 是動態分配主次設備號。register_chrdev()。是老版本的設備號註冊方式,只分配主設備號。從設備號在mknod的時候指定。
include/linux/cdev.h
– cdev類型是是字符設備描述的結構;
– 其中的設備號必須用“dev_t”類型來描述,高12位爲主設備號,低20位爲次設備號。
include/linux/kdev_t.h
– 在kdev_t.h頭文件中有一系列設備號處理的宏命令,用於處理各種設備號相關的數據。
如下,是完整的申請字符類設備號的程序:request_ascdev_num.c
以下代碼實現的功能是加載模塊時若通過“numdev_major”、“numdev_minor”傳入參數則靜態註冊字符類設備號;否則動態註冊字符類設備號(驅動模塊傳參數見博文:嵌入式Linux系統:驅動編程_驅動模塊傳參數 )。
#include <linux/init.h>
/*包含初始化宏定義的頭文件,代碼中的module_init和module_exit在此文件中*/
#include <linux/module.h>
/*包含初始化加載模塊的頭文件,代碼中的MODULE_LICENSE在此頭文件中*/
/*定義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>
#define DEVICE_NAME "ascdev"
#define DEVICE_MINOR_NUM 2
#define DEV_MAJOR 0
#define DEV_MINOR 0
MODULE_LICENSE("Dual BSD/GPL");
/*聲明是開源的,沒有內核版本限制*/
MODULE_AUTHOR("iTOPEET_dz");
/*聲明作者*/
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 int scdev_init(void)
{
int ret = 0;
dev_t num_dev;
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);
}
printk(KERN_EMERG "scdev_init!\n");
/*打印信息,KERN_EMERG表示緊急信息*/
return 0;
}
static void scdev_exit(void)
{
printk(KERN_EMERG "scdev_exit!\n");
unregister_chrdev_region(MKDEV(numdev_major,numdev_minor),DEVICE_MINOR_NUM);
}
module_init(scdev_init);
/*初始化函數*/
module_exit(scdev_exit);
/*卸載函數*/
編譯生成驅動模塊“request_ascdev_num.ko”。
程序運行時,若通過numdev_major傳入參數則靜態申請字符類設備號;否則動態申請字符類設備號。
使用命令 “cat /proc/devices”查看設備。