嵌入式Linux系統:驅動編程_註冊字符類設備號

        前面學習的雜項設備,主設備號已經固定爲 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”查看設備。

 

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章