块设备驱动程序——了解接收到的ioctl
Block device driver - Understanding received ioctl
我刚刚实现了一个虚拟块设备,在使用它时我看到了与 ioctls 相关的奇怪行为。
我的设备只是一个内存区域,分为两个 512 字节的扇区。我目前可以使用系统调用 read/write from/to 它在特定的偏移量。
该设备还受到保护,防止并发写入访问。它接受无限数量的reader,但一次只接受一个作者,并且只有当前没有人在阅读它。
Ioctls 尚未处理,但尽管如此,我仍在记录相关信息。
int block_mod_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
DEBUG("Entering IOCTL handling function\n");
switch(cmd)
{
default:
WARNING("Unknown ioctl call: %x\n", cmd);
WARNING("Ioctl: type=%x\tnumber=%x\tdirection=%x\tsize=%x\n", _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_DIR(cmd), _IOC_SIZE(cmd));
return -1;
}
return 0;
}
我在玩 dd
时发现了一个奇怪的行为,经过一番挖掘后我无法理解。
# dd if=/dev/blkmodtest of=file.out seek=10
[ 107.367797] Oppened in read only mode
[ 107.368595] Read access: 1 Write access: 0
[ 107.370367] Reading from device
[ 107.372939] Closed read only mode
[ 107.373690] Read access: 0 Write access: 0
2+0 records in
2+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00584625 s, 175 kB/s
# dd if=/dev/blkmodtest of=file.out skip=10
[ 111.982493] Oppened in read only mode
[ 111.983326] Read access: 1 Write access: 0
[ 111.985247] Unknown ioctl call: 80306d02
[ 111.986096] Ioctl: type=6d number=2 direction=2 size=30
[ 111.987618] Unknown ioctl call: 80306d02
[ 111.988436] Ioctl: type=6d number=2 direction=2 size=30
dd: /dev/blkmodtest: cannot skip: Invalid argument
[ 111.991032] Closed read only mode
[ 111.991705] Read access: 0 Write access: 0
0+0 records in
0+0 records out
0 bytes copied, 0.00783969 s, 0.0 kB/s
似乎 dd
正在发出我的驱动程序无法(显然)处理的 ioctl 调用。我知道我不应该给出 skip=10
,而是 seek=10
,因为我正在从设备上读取,但它是为了测试目的。
我目前正在尝试了解为什么发出这个ioctl以及是什么目的?
如果我很好地理解我找到的文档,ioctl 类型是 'm'
,应该在以下文件之一中描述 (source):
'm' 00-09 linux/mmtimer.h conflict!
'm' all linux/mtio.h conflict!
'm' all linux/soundcard.h conflict!
'm' all linux/synclink.h conflict!
'm' 00-19 drivers/message/fusion/mptctl.h conflict!
'm' 00 drivers/scsi/megaraid/megaraid_ioctl.h conflict!
我已经检查了这些文件,但找不到有用的信息来帮助我进一步了解具体情况。
设置循环设备(sudo losetup loop0 /path/to/some/image
),strace dd if=/dev/loop0 of=out.data skip=10 bs=40 count=2
的输出包含
open("/dev/loop0", O_RDONLY) = 3
dup2(3, 0) = 0
close(3) = 0
lseek(0, 0, SEEK_CUR) = 0
ioctl(0, MTIOCGET, 0x7fffac670080) = -1 EINVAL (Invalid argument)
lseek(0, 400, SEEK_CUR) = 400
fstat(0, {st_mode=S_IFBLK|0660, st_rdev=makedev(7, 0), ...}) = 0
表示 dd
正在尝试对您的块设备执行 MTIOCGET
ioctl。 man 4 st
显示
The st driver provides the interface to a variety of SCSI tape devices.
[...]
MTIOCGET — get status
This request takes an argument of type (struct mtget *).
换句话说,dd
怀疑您的块设备可能是某种 SCSI 磁带设备,并使用您看到的 ioctl()
询问它的状态。
你的 driver 到 return EINVAL
完全没问题;就是这样循环设备也是如此。
我刚刚实现了一个虚拟块设备,在使用它时我看到了与 ioctls 相关的奇怪行为。
我的设备只是一个内存区域,分为两个 512 字节的扇区。我目前可以使用系统调用 read/write from/to 它在特定的偏移量。
该设备还受到保护,防止并发写入访问。它接受无限数量的reader,但一次只接受一个作者,并且只有当前没有人在阅读它。
Ioctls 尚未处理,但尽管如此,我仍在记录相关信息。
int block_mod_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
DEBUG("Entering IOCTL handling function\n");
switch(cmd)
{
default:
WARNING("Unknown ioctl call: %x\n", cmd);
WARNING("Ioctl: type=%x\tnumber=%x\tdirection=%x\tsize=%x\n", _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_DIR(cmd), _IOC_SIZE(cmd));
return -1;
}
return 0;
}
我在玩 dd
时发现了一个奇怪的行为,经过一番挖掘后我无法理解。
# dd if=/dev/blkmodtest of=file.out seek=10
[ 107.367797] Oppened in read only mode
[ 107.368595] Read access: 1 Write access: 0
[ 107.370367] Reading from device
[ 107.372939] Closed read only mode
[ 107.373690] Read access: 0 Write access: 0
2+0 records in
2+0 records out
1024 bytes (1.0 kB, 1.0 KiB) copied, 0.00584625 s, 175 kB/s
# dd if=/dev/blkmodtest of=file.out skip=10
[ 111.982493] Oppened in read only mode
[ 111.983326] Read access: 1 Write access: 0
[ 111.985247] Unknown ioctl call: 80306d02
[ 111.986096] Ioctl: type=6d number=2 direction=2 size=30
[ 111.987618] Unknown ioctl call: 80306d02
[ 111.988436] Ioctl: type=6d number=2 direction=2 size=30
dd: /dev/blkmodtest: cannot skip: Invalid argument
[ 111.991032] Closed read only mode
[ 111.991705] Read access: 0 Write access: 0
0+0 records in
0+0 records out
0 bytes copied, 0.00783969 s, 0.0 kB/s
似乎 dd
正在发出我的驱动程序无法(显然)处理的 ioctl 调用。我知道我不应该给出 skip=10
,而是 seek=10
,因为我正在从设备上读取,但它是为了测试目的。
我目前正在尝试了解为什么发出这个ioctl以及是什么目的?
如果我很好地理解我找到的文档,ioctl 类型是 'm'
,应该在以下文件之一中描述 (source):
'm' 00-09 linux/mmtimer.h conflict!
'm' all linux/mtio.h conflict!
'm' all linux/soundcard.h conflict!
'm' all linux/synclink.h conflict!
'm' 00-19 drivers/message/fusion/mptctl.h conflict!
'm' 00 drivers/scsi/megaraid/megaraid_ioctl.h conflict!
我已经检查了这些文件,但找不到有用的信息来帮助我进一步了解具体情况。
设置循环设备(sudo losetup loop0 /path/to/some/image
),strace dd if=/dev/loop0 of=out.data skip=10 bs=40 count=2
的输出包含
open("/dev/loop0", O_RDONLY) = 3
dup2(3, 0) = 0
close(3) = 0
lseek(0, 0, SEEK_CUR) = 0
ioctl(0, MTIOCGET, 0x7fffac670080) = -1 EINVAL (Invalid argument)
lseek(0, 400, SEEK_CUR) = 400
fstat(0, {st_mode=S_IFBLK|0660, st_rdev=makedev(7, 0), ...}) = 0
表示 dd
正在尝试对您的块设备执行 MTIOCGET
ioctl。 man 4 st
显示
The st driver provides the interface to a variety of SCSI tape devices.
[...]
MTIOCGET — get status
This request takes an argument of type (struct mtget *).
换句话说,dd
怀疑您的块设备可能是某种 SCSI 磁带设备,并使用您看到的 ioctl()
询问它的状态。
你的 driver 到 return EINVAL
完全没问题;就是这样循环设备也是如此。