我定义了以下chardev:
·H
#define MAJOR_NUM 245
#define MINOR_NUM 0
#define IOCTL_MY_DEV1 _IOW(MAJOR_NUM, 0, unsigned long)
#define IOCTL_MY_DEV2 _IOW(MAJOR_NUM, 1, unsigned long)
#define IOCTL_MY_DEV3 _IOW(MAJOR_NUM, 2, unsigned long)
模块.c
static long device_ioctl(
struct file* file,
unsigned int ioctl_num,
unsigned long ioctl_param)
{
...
}
static int device_open(struct inode* inode, struct file* file)
{
...
}
static int device_release(struct inode* inode, struct file* file)
{
...
}
struct file_operations Fops = {
.open=device_open,
.unlocked_ioctl= device_ioctl,
.release=device_release
};
static int __init my_dev_init(void)
{
register_chrdev(MAJOR_NUM, "MY_DEV", &Fops);
...
}
module_init(my_dev_init);
我的用户代码
ioctl(fd, IOCTL_MY_DEV1, 1);
始终以相同的错误失败:ENOTTY
设备不适当的ioctl
我见过类似的问题: 即
Linux kernel module - IOCTL usage returns ENOTTY
Linux Kernel Module/IOCTL: inappropriate ioctl for device
但他们的解决方案并不适合我
答案 0 :(得分:3)
ENOTTY
。我担心你的功能没有很好地注册,可能是因为你已经在.unlocked_ioctl
结构的struct file_operations
字段中注册了它。
如果您在锁定版本的函数中注册它,可能会得到不同的结果。最可能的原因是inode被锁定用于ioctl调用(因为它应该是,以避免对同一设备同时进行read
或write
操作的竞争条件)
抱歉,我无法访问linux源代码树以获取要使用的字段的正确名称,但您肯定可以自己找到它。
我发现您使用了宏_IOW
,使用主号码作为唯一标识符。这可能不是你想要的。 _IOW
的第一个参数尝试确保ioctl调用获取唯一标识符。获取此类标识符没有一般方法,因为这是您在应用程序代码和内核代码之间创建的接口契约。所以使用主要数字是不好的做法,原因有两个:
_IOW
是很久以前建立的一个宏(很久以前从linux内核诞生之后)试图解决这个问题,允许你为每个驱动程序选择一个不同的字符(但不依赖于其他对于具有ioctl调用的设备没有与其他设备驱动程序冲突的内核参数,由于上述原因)。这种冲突的可能性很低,但是一旦发生这种情况,你可能会导致错误的机器状态(你已经向错误的设备发出了有效的,工作的ioctl调用)
古代unix(和早期linux)内核使用不同的字符来构建这些调用,例如,tty
驱动程序使用'T'
作为_IO*
宏的参数,使用scsi磁盘'S'
等等。
我建议你选择一个随机数(不会出现在linux内核列表的其他地方),然后在你的所有设备中使用它(可能你写的驱动程序少于内核中的驱动程序)并选择不同的ioctl id为每个ioctl调用。以这种方式使用已注册的ioctl维护本地ioctl文件比尝试猜测始终有效的值要好得多。
另外,查看_IO*
宏的定义应该非常具有说明性:)