一、字符设备注册
内核在内部使用类型 struct cdev 的结构来代表字符设备.
在内核调用你的设备操作前, 你需要编写分配并注册一个或几个这样的结构. 为此,
你的代码应当包含<linux/cdev.h>, 这个结构和它的关联帮助函数定义在这里.
有 2 种方法来分配和初始化一个这些结构.
1.定义cdev结构并申请内存,然后将其与操作函数指针相关联
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
2.如果你想将 cdev 结构嵌入一个你自己的设备特定的结构 ,在这种情况下, 你应当初始化你已经分配的结构, 使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
一旦 cdev 结构建立, 最后的步骤是把它告诉内核, 调用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
这里, dev 是 cdev 结构, num 是这个设备响应的第一个设备号, count 是应当关联到设备的设备号的数目.
常常 count 是 1, 但是有多个设备号对应于一个特定的设备的情形.
例如, 设想 SCSI 磁带驱动, 它允许用户空间来选择操作模式(例如密度), 通过安排多个次编号给每一个物理设备。
调用可能失败. 它返回一个负的错误码 。这时需要做错误处理,为从系统去除一个字符设备, 调用:
void cdev_del(struct cdev *dev);
通常我们使用一个 set_cdev 函数来完成 cdev 的初始化和注册,eg:
static void scull_setup_cdev(struct scull_dev *dev, int index)
{
int err, devno = MKDEV(scull_major, scull_minor + index);
cdev_init(&dev->cdev, &scull_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &scull_fops;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}
二、设备号申请和注销
int register_chrdev_region(dev_t first, unsigned int count, char *name)
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name)
void unregister_chrdev_region(dev_t first, unsigned int count);
允许驱动分配和释放设备编号的范围的函数.
register_chrdev_region 应当用在事先知道需要的主编号时;
对于动态分配, 使用 alloc_chrdev_region 代替.