为什么内核使用默认的块驱动程序而不是我的驱动程序代码?

时间:2014-04-24 10:14:43

标签: linux kernel block-device

我写了一个块驱动程序,它创建了一个虚拟块设备(sbd0)。我注册了该块设备的所有设备操作:(请参阅2.6.32内核源代码中的include/linux/blkdev.h

static struct block_device_operations sbd_ops = {
    .owner           = THIS_MODULE,
    .open            = sbd_open,
    .release         = sbd_close,
    .ioctl           = sbd_ioctl,
    .getgeo          = sbd_getgeo,
    .locked_ioctl    = sbd_locked_ioctl,
    .compat_ioctl    = sbd_compat_ioctl,
    .direct_access   = sbd_direct_access,
    .media_changed   = sbd_media_changed,
    .revalidate_disk = sbd_revalidate_disk
};

我编译了驱动程序。我插入了模块并创建了/dev/sbd0。现在我想测试我的驱动程序代码。所以我写了一个如下的应用程序。

fd = open("/dev/sbd0", O_RDONLY); 
retval = ioctl(fd, BLKBSZGET, &blksz); //trying to get logical block size

输出为:4096

我想知道:我没有为BLKBSZGET实施ioctl。它没有调用我的sbd_ioctl,而是使用了默认驱动程序并给了我结果。对于openclose调用它执行sbd_opensbd_close(我已实施)。然后我尝试了:

retval = ioctl(fd, HDIO_GETGEO, &geoinfo);

它调用了sbd_getgeo,但我认为它会调用sbd_ioctl

以下是我的问题:

  1. 我实现了一个驱动程序并创建了一个设备。如果我在该设备上执行任何操作,则必须调用我的驱动程序应用程序。但是它如何使用我的一些驱动程序函数和几个默认的驱动程序函数?
  2. ioctl(fd, HDIO_GETGEO, ..)没有调用.ioctl来电,但却调用.getgeo。这怎么可能?

1 个答案:

答案 0 :(得分:6)

ioctl调度由blkdev_ioctl函数处理,该函数将直接处理一些ioctl,而不会调用您的驱动程序的特定例程。

对于HDIO_GETGEO,它直接调用您的驱动程序getgeo函数(来自内核3.13.6,自2.6.32以来似乎没有太大变化):

[...]
/*
 * We need to set the startsect first, the driver may
 * want to override it.
 */
memset(&geo, 0, sizeof(geo));
geo.start = get_start_sect(bdev);
ret = disk->fops->getgeo(bdev, &geo); /* <- here */
[...]

对于BLKBSZGET,它会调用block_size(bdev)),只会返回bdev->bd_block_size

如果您需要知道其他ioctl会发生什么,您会在blkdev_ioctl中找到block/ioctl.c