ldd3サンプルコードでファイル操作が2回割り当てられるのはなぜですか?

ldd3サンプルコードでファイル操作が2回割り当てられるのはなぜですか?

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;
}

関連情報