我写了一个块驱动程序,它创建了一个虚拟块设备(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
,而是使用了默认驱动程序并给了我结果。对于open
,close
调用它执行sbd_open
和sbd_close
(我已实施)。然后我尝试了:
retval = ioctl(fd, HDIO_GETGEO, &geoinfo);
它调用了sbd_getgeo
,但我认为它会调用sbd_ioctl
。
以下是我的问题:
ioctl(fd, HDIO_GETGEO, ..)
没有调用.ioctl
来电,但却调用.getgeo
。这怎么可能?答案 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
。