块设备驱动程序-理解接收到的ioctl
我刚刚实现了一个虚拟块设备,当我玩它的时候,我看到了与ioctl相关的奇怪行为 我的设备只是一个内存区域,分为两个512字节的扇区。目前,我可以使用系统调用在特定偏移量对其进行读/写操作 该设备还可以防止并发写访问。它接受无限数量的读卡器,但一次只能接受一个写卡器,并且只有在当前没有人从中读取的情况下 IOCTL尚未处理,但尽管如此,我还是记录了相关信息块设备驱动程序-理解接收到的ioctl,c,linux-kernel,ioctl,block-device,C,Linux Kernel,Ioctl,Block Device,我刚刚实现了一个虚拟块设备,当我玩它的时候,我看到了与ioctl相关的奇怪行为 我的设备只是一个内存区域,分为两个512字节的扇区。目前,我可以使用系统调用在特定偏移量对其进行读/写操作 该设备还可以防止并发写访问。它接受无限数量的读卡器,但一次只能接受一个写卡器,并且只有在当前没有人从中读取的情况下 IOCTL尚未处理,但尽管如此,我还是记录了相关信息 int block_mod_ioctl(struct block_device *bdev, fmode_t mode, unsigned i
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的目的是什么
如果我很了解我找到的文档,那么ioctl类型是'm'
,应该在以下文件()中进行描述:
我已经检查了这些文件,但是我找不到有用的信息来帮助我进一步了解在这种特定情况下发生了什么。设置一个循环设备(sudolosetup 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。显示
st驱动程序为各种SCSI磁带设备提供接口。
[…]
MTIOCGET-获取状态
此请求接受类型为(struct mtget*)的参数 换句话说,
dd
怀疑您的块设备可能是某种SCSI磁带设备,并使用您看到的ioctl()
向它询问状态
您的驾驶员完全可以为此返回EINVAL
;例如,环路设备也是这样做的
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