字符設備驅動的學習
1.首先介紹幾個重要的結構體:
1.1 cdev結構體描述字符設備
Struct cdev
{
struct kobject kobj; /*內嵌的kobject對象*/
sruct module *owner; /*所屬模塊*/
struct file_operations *ops; //文件操作結構體
Struct list_head list;
dev_t dev ; //設備號
unsigned int count;
}
其中file_operations定義了字符設備驅動提供給虛擬文件系統的接口函數,void cdev_init(struct cdev*, struct file_operations *);這個函數用於初始化cdev的成員,並且建立cdev和file_operations之間的鏈接。
void cdev_init(struct cdev *cdev,struct file_operations *fops)
{
memset(cdev, 0 , sizeof *cdev);
INIT_LIST_HEAD(&cdev->list);
cdev->kobj.ktype = &ktype_cdev_default;
kobject_init(&cdev->kobj);
cdev->ops = fops; //講傳入的文件操作結構體指針賦值給cdev的ops*
}
cdev_add()函數和cdev_del()函數用於向操作系統添加和刪除一個cdev,完成字符設備的註冊與註銷。
註冊字符設備之前,首先調用register_chardev_region()或者alloc_chrdev_region函數向系統申請設備號,這兩個函數的原型如下:
int register_chardev_region(dev_t from ,unsigned int count ,const char *name);
int alloc_chrdev_region(dev_t *dev, unsigned int baseminor ,unsigned int count ,const char *name);
其中第二個函數用於向設備動態申請未被佔用的設備號。
字符設備驅動的組成
2.1.定義一個xxx_dev_t結構體可以包含設備所涉及的cdev,私有數據以及信號量等信息。常見的設備結構體、模塊加載和卸載函數形式如下所示
struct xxx_dev_t
{
struct cdev cdev;
、、、、、
} XXX_dev;
//獲取字符設備號
static int __init xxx_init(void)
{
....
cdev_init(&xxx_dev.cdev, &xxx_fops)
xxx_dev.cdev.owner = THIS_MODULE;
if(xxx_major)
{
register_chrdev_region(xxx_dev_no, 1 , DEV_NAME);
}
else
{
alloc_chrdev_region(&xxx_dev_no, 0, 1, DEV_NAME);
}
ret = cdev_add(&xxx_dev.cdev , xxx_dev_no, 1); //註冊設備
.。。。。。
}
//設備驅動模塊卸載函數
static void __exit xxx_exit(void )
{
unregister_chrdev_region(xxx_dev_ni, 1);//釋放佔用的設備號
cdev_del(&xxx_dev.cdev); //註銷設備
}
2.2.file_operations結構體中的成員函數最常見的3個函數如下所示。
ssize_t xxx_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos )
{
.。。。
copy_to_user(buf , ... , ....);
。。。
}
//寫設備
ssize_t xxx_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
。。。
copy_from_user(。。。, buf , 。。。);
}
int xxx_ioctl(stuect inode *inode ,struct file *filp ,unsigned int cmd ,unsigned int long arg)
{
.....
switch(cmd)
{
case XXX_CMD1:
.....
break;
case XXX_CMD2:
.....
break;
default:
return -ENOTTY;
}
return 0;
}
字符設備室3大類設備(字符設備、塊設備和網絡設備)中較簡單的一類設備,其驅動程序中完成的主要工作是初始化、添加和刪除cdev結構體,申請和釋放設備號,以及填充file_operations結構體中的操作函數,實現file_operations結構體重的read()、write()和ioctl()等函數是驅動設計的主體工作。