这个问题是关于我在作为 Oracle Virtual Box 中的虚拟机运行的 Ubuntu Linux 操作系统中从用户空间到内核空间的 ioctl 错误调用。编译模块代码后,使用“sudo insmod ioctl_module.ko”命令将其加载到 Linux 内核中,您可以通过下面的消息列表看到成功。出于某种原因,从用户空间到内核模块函数的 ioctl 调用说其中一个参数无效,我看不出它是无效的。(另外,这只是我第二次发布堆栈溢出问题,所以我希望我正确地遵循了你的约定!)谢谢,凯伦
用户级代码错误信息:
saasbook@saasbook:~/cs552/osPrimer/invokeKernelServices/user_level_code$./ioctl_test
testStruct.field1 的大小 = 1
testStruct.field2 的大小 = 1
第一个 ioctl:参数无效
ioctl_test.c 的代码清单:
https://gist.github.com/KarenWest/6629582
可以看到 ioctl_module 在内核中:
/invokeKernelServices$ dmesg
[13563.849593] 加载模块
[13578.846063] pseudo_device_ioctl
ioctl_module.c 的代码列表:
https://gist.github.com/KarenWest/6629557
我现在可以更具体地回答几天前的问题。使用 ioctl.h 位定义,使用 _IOW 的#define 宏,将它们一起移位和 oring,我看到 IOCTL_TEST = 0x4002006 是正确的,而 cmd = 0x804a030 是不正确的,但我无法弄清楚为什么 cmd 有错误价值。cmd 是上述 ioctl 入口点的参数:
static int pseudo_device_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
因此,我查看了 proc_fs.h 输入文件的 proc_dir_entry 结构,其中该结构中的 proc_fops 指针设置为我的 ioctl 入口点函数,将 pseudo_dev_proc_operations 初始化为 file_operations 结构,并将 proc_entry 初始化为指向 proc_dir_entry 结构的指针(所有这些都在上面git上的代码链接中),所有这些都在ioctl_module.c的initialization_routine()中初始化,我知道一旦代码在ioctl_test.c级别调用,操作系统就应该用正确的值设置这个ioctl设置为将其定向到我的 ioctl 函数,它确实如此。但是,发送到我的 ioctl 函数设置 (cmd) 的参数不正确,并且与 IOCTL_TEST 不匹配,这就是失败的原因。
pseudo_dev_proc_operations.unlocked_ioctl = pseudo_device_ioctl;
pseudo_dev_proc_operations.compat_ioctl = pseudo_device_ioctl;
proc_entry = create_proc_entry("ioctl_test", 0666, NULL);
proc_entry->proc_fops = &pseudo_dev_proc_operations;
所以我跟着 proc_fs.h 的 proc_fops 指针(它被初始化为 pseudo_dev_proc_operations,它把它带到我的 ioctl pseudo_device_ioctl 函数)看看为什么 cmd 参数在处理过程中可能会搞砸,我迷失了 - 不知道为什么会这样。
如果有人有任何进一步的评论可以帮助我找出我哪里出错了,请告诉我。谢谢!凯伦
这可能会有所帮助 - 只需阅读以下内容:
“Linux内核模块编程指南:
第 7 章 与设备文件对话
7.1。与设备文件对话(写入和 IOCTL)”