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;
合計が2回割り当てられていることがわかりますscull_fops
。なぜですか?cdev_init()
cdev.ops
答え1
scull_fops
いいえ分散二度、つまり使用される二重。それ限られた 同じファイル内の他の場所、そのアドレスはに渡され、cdev_init
に割り当てられますdev->cdev.ops
。
あなたが言及したように、toへの明示的な割り当てはdev->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
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;
}