【问题标题】:ioctl - invalid argumentioctl - 无效参数
【发布时间】:2012-12-15 11:11:25
【问题描述】:

我有

#define IOCTL_ALLOC_MSG _IO(MAJOR_NUM, 0) 
#define IOCTL_DEALLOC_MSG _IO(MAJOR_NUM, 1)

在头文件中。

在我写的驱动文件中:

struct file_operations memory_fops = {
  unlocked_ioctl: device_ioctl,
  open: memory_open,
  release: memory_release
};


int memory_init(void) {
  int result;

  /* Registering device */
  result = register_chrdev(MAJOR_NUM, "memory", &memory_fops);
  if (result < 0) {
    printk("<1>memory: cannot obtain major number %d\n", MAJOR_NUM);
    return result;
  }

  allocfunc();

  printk("<1>Inserting memory module\n");
  return 0;

}

int device_ioctl(struct inode *inode,   /* see include/linux/fs.h */
         struct file *file, /* ditto */
         unsigned int ioctl_num,    /* number and param for ioctl */
         unsigned long ioctl_param)
{
    /* 
     * Switch according to the ioctl called 
     */
    printk ( "<l> inside ioctl \n" );
    switch (ioctl_num) {
    case IOCTL_ALLOC_MSG:
        allocfunc();
        break;
    case IOCTL_DEALLOC_MSG:
        deallocfunc();
        break;
    }

    return 0;
}

我创建了像

这样的字符文件
mknod /dev/memory c 60 0

应用调用失败

int main(int argc, char *argv[]) {
    FILE * memfile;

    /* Opening the device parlelport */
    memfile=fopen("memory","r+");
    if ( memfile <0) {
        printf ( " cant open file \n");
        return -1;
    }

    /* We remove the buffer from the file i/o */
    int ret_val;
    if ( argc > 1 ) {
        if ( strcmp (argv[1], "mem" ) ==0 ) {


            ret_val = ioctl(memfile, IOCTL_ALLOC_MSG);

            if (ret_val < 0) {
                printf("ioctl failed. Return code: %d, meaning: %s\n", ret_val, strerror(errno));
                return -1;
            }
        }

当我运行应用程序时,我得到“ioctl failed. Return code: -1, meaning: Invalid argument” in : strerror(errno)

打印:

Inserting memory module

仅供参考,我尝试了“/dev/memory”“memory”不同的名称和主要数字组合 - 但徒劳无功。

【问题讨论】:

  • MAJOR_NUM 的值是多少?您确定 60 尚未被其他驱动程序使用吗?即你的 init_module() 函数是什么样的,如果它应该调用register_chrdev(),结果是什么?此外,您甚至没有显示对strerror()....的调用。
  • MAJOR_NUM 为 60,未被其他驱动程序使用int memory_init(void) { int result; /* 注册设备 */ result = register_chrdev(MAJOR_NUM, "memory", &memory_fops); if (result memory: 无法获取主编号 %d\n", MAJOR_NUM);返回结果; } allocfunc(); printk("插入内存模块\n");返回0; } ---app---------ret_val = ioctl(memfile, IOCTL_ALLOC_MSG); if (ret_val
  • 好的,所以也许您可以将其编辑到上面的代码中?并且还请添加fopen() 之间的所有代码,包括对strerror() 的调用(特别是如果您检查了fopen() 的结果),并显示模块加载时的任何控制台输出直到ioctl() 调用的时间(即我想在那里看到printk() 和任何其他相关输出。
  • 我用init、app和printk更新了原帖。
  • 为什么在初始化模块时会调用子程序allocFunc()?进程在设备上执行 ioctl 时不应该调用该函数。由于您分配的不是宏 IOCTL_ALLOC_MSG 定义了读/写权限。

标签: c linux driver


【解决方案1】:

您将FILE* 传递给ioctl() 函数,而它需要一个文件描述符,即int。

它至少应该产生一个很大的警告,说你正在将指针转换为没有强制转换的整数,不是吗?

有两个明显的解决方案:

  1. 使用fileno() 函数从FILE* 获取文件描述符。它应该类似于ioctl(fileno(memfile), IOCTL_ALLOC_MSG)。
  2. 使用open() 而不是fopen()。如果您正在编写低级代码,这是首选解决方案,因为您避免了FILE* 强加的额外抽象层(所有缓冲的东西等等)。

【讨论】:

  • 该死!我完全错过了那个!
  • @furion:不客气!尝试使用-Wall 进行编译。它应该发出警告。也许您忘记了#include &lt;sys/ioctl.h&gt;,而您正在获得自动函数声明;如果是这种情况,您也应该收到警告。
【解决方案2】:

我假设将 fopen("memory") 更改为 fopen("/dev/memory1") 将解决您的代码的初始问题。

@SunEric 在对您的问题的评论中还指出,您在驱动程序的初始化函数 (memory_init()) 中调用了 allocFunc(),但这似乎是您希望您的 IOCTL_ALLOC_MSG 执行的操作。这很可能是您需要解决的下一个问题。

【讨论】:

  • 抱歉造成混淆,我尝试了“/dev/memory”“memory”不同的名称和主要数字组合 - 但徒劳无功。我已经尝试使用 allocFunc() 没有等,请忽略小问题。我能够成功看到 memory_init() 中的 printk。
猜你喜欢
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-05
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
相关资源
最近更新 更多