https://github.com/martinezjavier/ldd3/blob/master/scull/main.c#L601
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;
我们可以看到和scull_fops
被分配了两次,为什么呢?cdev_init()
cdev.ops
答案1
scull_fops
不是分配的两次,就是用过的两次。它是定义的 同一文件中的其他地方,然后它的地址被传递到cdev_init
,并分配给dev->cdev.ops
。
正如您所提到的,这种显式分配 todev->cdev.ops
是不必要的,因为cdev_init
它也是如此。作为约翰·迈林 说,这是 LDD3 示例代码中的一个低效率问题——示例代码比 中的相应行更新cdev_init
,因此在编写时就已经没有必要了。 (看看是否在其他地方重现了同样的错误,看看有多少“真正的”驱动程序代码是基于 LDD3 示例编写的,这将是很有趣的!)
该函数可以简化为
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;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding scull%d", err, index);
}
答案2
请参阅此链接以确认它执行两次:
https://github.com/torvalds/linux/blob/6f0d349d922ba44e4348a17a78ea51b7135965b1/fs/char_dev.c#L656
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
memset(cdev, 0, sizeof *cdev);
INIT_LIST_HEAD(&cdev->list);
kobject_init(&cdev->kobj, &ktype_cdev_default);
cdev->ops = fops;
}