如何在Linux 2.6.29中的ioctl()系统调用中解码arg指针?

Jun*_*aid 2 c linux ioctl system-calls linux-kernel

我想打印传递给linux系统调用的所有参数值.ioctl()例如,在我的情况下,我有以下原型和打印声明.

asmlinkage long our_sys_ioctl(unsigned int fd ,  unsigned int cmd , unsigned long arg)
{
    printk ("fd=%u, cmd=%u and arg=%lu \n ", fd, cmd, arg);
    return original_call_ioctl(fd , cmd , arg);
}
Run Code Online (Sandbox Code Playgroud)

据我所知,fd是驱动程序文件的文件描述符,cmd定义了驱动程序,ioctl编号,操作类型和参数大小.但我对arg参数感到困惑,要么是指向内存的指针,要么只是大多数文档称之为立即值的指针.

通过使用此arg参数,如果unsigned long arg像上面给出的那样传递内存内容而不是指针,我该如何获取内存?

Rol*_*and 5

argioctl 的参数在通用vfs级别是不透明的.如何解释它取决于实际处理它的驱动程序或文件系统.所以它可能是指向用户空间内存的指针,也可能是索引,标志等等.它甚至可能未被使用,并且通常以0传递.

例如,查看TCSBRKPioctl 的实现drivers/tty/tty_io.c:

long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
//...
       case TCSBRKP:   /* support for POSIX tcsendbreak() */
            return send_break(tty, arg ? arg*100 : 250);
Run Code Online (Sandbox Code Playgroud)

您可以查看ioctl_list(2)手册页以查看各种ioctl所采用的参数; 该列表上具有int或其他非指针参数的所有条目都是其他示例.

所以你可以做点什么

    void __user *argp = (void __user *) arg;
Run Code Online (Sandbox Code Playgroud)

然后使用copy_from_user()get_user()读取arg指向的内存,但如果参数不是指针则可能会失败.在通用的ioctl系统调用中,你可能真的不想拥有一个包含每个可能的ioctl的巨大表格.