裝置号
裝置号由主裝置号和次裝置号組成。linux下,一切裝置皆檔案,所有的裝置都能在/dev目錄下找到相應的檔案。這些檔案除了名字不一樣以外,還每個裝置檔案都有不一樣的裝置号;
一般地,主裝置号對應一個類型的驅動裝置,之是以有次裝置号,它是用來驅動同類型的裝置。如序列槽,所有的序列槽共用一個主裝置号,每個序列槽有不同的次裝置号。
dev_t類型用來儲存裝置編号(包含主裝置号和次裝置号),實際上是一個32位整數,12位用來表示主裝置号,後20位表示次裝置号。
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)
//提取主裝置号
#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
//提取次裝置号
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
//生成裝置号
#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))
裝置号的配置設定和釋放
靜态配置設定
/**
* register_chrdev_region() - register a range of device numbers
* @from: the first in the desired range of device numbers; must include
* the major number.
* @count: the number of consecutive device numbers required
* @name: the name of the device or driver.
*
* Return value is zero on success, a negative error code on failure.
*/
int register_chrdev_region(dev_t from, unsigned count, const char *name)
指定從裝置号from開始,申請count個裝置号,在/proc/devices中的名字為name
動态配置設定
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
動态申請從次裝置号baseminor開始的count個裝置号,在/proc/devices中的名字為name,并通過dev指針把配置設定到的裝置号傳回給調用函數者。
釋放
void unregister_chrdev_region(dev_t from, unsigned count)
裝置注冊
字元裝置struct cdev
struct cdev {
struct kobject kobj;
struct module *owner;//一般初始化為THIS_MODULE
const struct file_operations *ops;//檔案操作結構體
struct list_head list;
dev_t dev;//裝置号
unsigned int count;//添加的裝置個數
};
注冊的三個步驟:
1)配置設定cdev;
2)初始化cdev;
3)添加cdev;
配置設定
直接定義struct cdev test_cdev;
或者動态配置設定
truct cdev* test_cdev;
test_cdev = cdev_alloc();
初始化
/**
* cdev_init() - initialize a cdev structure
* @cdev: the structure to initialize
* @fops: the file_operations for this device
*
* Initializes @cdev, remembering @fops, making it ready to add to the
* system with cdev_add().
*/
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
這個函數幹了兩件事情:
1)核心自己填充了結構體中list和kobj的内容
2)把傳入的檔案操作結構體也填充進去
一般的,還要手工定義結構體成員owner。
添加
将cdev結構體與裝置号關聯起來:
int cdev_add(struct cdev *cdev, dev_t dev, unsigned count)
參數:
cdev:指定要被添加的cdev結構體;
dev:對應的裝置号
count:從裝置号dev開始添加count個裝置.
函數幹了也兩件事:
1)把cdev結構體中還沒填充的兩個成員dev和count按照傳入參數指派。
2)把cdev結構體中傳入核心,這樣核心就知道對應裝置号和具體的檔案操作結構體了。
删除
void cdev_del(struct cdev *p)