字符設備
設備號相關操作宏:
設備號 = MKDEV(設備號,次設備號);
主設備號 = MAJOR(設備號);
次設備號 = MINOR(設備號);
分配和釋放設備編號
1、分配
在構建一個字符設備之前,驅動程序首先要獲得一個或者多個設備編號,這類似一個營業執照,有了營業執照纔在內核中正常工作營業。完成此工作的函數是:
1.1已知主設備號:(靜態申請)
int register_chrdev_region(dev_t first, unsigned int count, const char *name);
1.first:是要分配的設備編號範圍的起始值。count是連續設備的編號的個數。
2.name: 是和該設備編號範圍關聯的設備名稱,他將出現在/proc/devices和sysfs中。
3.返回值:成功返回0,失敗返回負的錯誤碼。
1.2、未知主設備號:(動態申請)
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, const char *name);
1:參數一:是輸出型參數,獲得一個分配到的設備號。可以用MAJOR宏和MINOR宏,將主設備號
和次設備號,提取打印出來,看是自動分配的是多少,方便我們在mknod創建設備文
件時用到主設備號和次設備號。 mknod /dev/xxx c 主設備號 次設備號
2:參數二:次設備號的基準,從第幾個次設備號開始分配。
3:參數三:次設備號的個數。
4:參數四:驅動的名字。
5:返回值:小於0,則錯誤,自動分配設備號錯誤。否則分配得到的設備號就被第一個參數帶出來。
2、釋放:
在不使用時需要釋放這些設備編號,已提供其他設備程序使用:
void unregister_chrdev_region(dev_t dev, unsigned count);
3、編程步驟:
//1.3定義初始化硬件操作方法對象
static struct file_operations xxx_fops = {
.owner = THIS_MODULE,
.open = xxx_open,
.release = xxx_close,
.read = xxx_read,
.write = xxx_write,
...
};
//1.1定義設備號對象
static dev_t devid;
//1.2定義字符設備對象
static struct cdev xxx_cdev;
/*入口函數*/
static int xxx_init(void)
{
//2.1.申請設備號
alloc_chrdev_region(&devid,0,1,"name");
//設備名稱
//2.2初始化字符設備對象
cdev_init(&xxx_cdev,&xxx_fops);
//2.3安裝字符設備對象到內核
cdev_add(&xxx_cdev,devid,1);//1爲次設備個數
...
return 0;
}
//出口函數
static void xxx_exit(void)
{
//2.4卸載字符設備對象
cdev_del(&xxx_cdev);
//2.5釋放設備號
unregister_chrdev_region(devid,1);
}
insmod xxx.ko --加載驅動
rmmod xxx --卸載驅動
lsmod --查看驅動
cat /proc/devices//查看申請的主設備號
#======================================
設備文件的創建方法
1.手工創建:利用mknod命令
mknod /dev/設備文件名 c 主設備號 次設備號
例如: mknod /dev/zhangsan c 250 0
2.自動創建
//1.定義設備類(樹枝)指針
struct class *cls;
//2.創建設備類(先長樹枝),設備類名爲name
cls = class_create(THIS_MODULE,"name");
//3.創建設備文件,自動生成/dev/xxx_name
device_create(cls,NULL,devid,NULL,"xxx_name");
//devid申請的設備號,xxx_name設備文件名
//4.自動刪除設備文件
device_destroy(cls,devid);
//5.自動刪除設備類
class_destroy(cls);
混雜設備:
//1.定義初始化混雜設備對應的硬件操作方法
struct file_operations xxx_fops = {
... ...
};
//2.定義初始化混雜設備對象
struct miscdevice xxx_misc = {
.minor =MISC_DYNAMIC_MINOR,
.name = "",
.fops = &xxx_fops
};
//3.安裝混雜設備對象到內核
misc_register(&xxx_misc);
//4.卸載混雜設備對象
misc_deregister(&xxx_misc);