【问题标题】:How Linux knows which ioctl function to call?Linux 如何知道调用哪个 ioctl 函数?
【发布时间】:2014-07-10 09:50:04
【问题描述】:

这是用户空间中的ioctl 调用:

int ioctl(int fd, int cmd, ...);

据我所知,当我们想要执行 IO 操作时,我们使用一组请求(命令)定义自己的 ioctl 函数,将我们的 ioctl 分配给 file_operations 结构,如下所示:

struct file_operations fops = {
 .read = device_read,
 .write = device_write,
 .ioctl = device_ioctl, // device_ioctl is our function
 .open = device_open,
 .release = device_release,
};

与用户空间界面相比,device_ioctl 函数的定义不同:

static long device_ioctl(struct file *f, unsigned int cmd, unsigned long arg)

我认为基于文件描述符,内核可以得到合适的文件结构,调用设备的ioctl

这只是一个猜测,因为我找不到内核根据传递给通用ioctl 接口的文件描述符fd 选择适当ioctl 函数的通用函数定义?我只能找到 3 个 ioctl 定义,但显然这些只是设备的定义,而不是内核:ioctl

【问题讨论】:

标签: c linux linux-kernel linux-device-driver ioctl


【解决方案1】:

查看 Linux 源代码 fs/ioctl.c (http://lxr.free-electrons.com/source/fs/ioctl.c)
在那里你会看到 ioctl 的系统调用:

SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)

这依次调用 do_vfs_ioctl(),它调用 vfs_ioctl(),然后调用在 file_operations 结构中为该文件系统定义的 unlocked_ioctl 函数。
这将是您注册的 device_ioctl 函数。

【讨论】:

    【解决方案2】:

    device_ioctl 是一个函数指针。内核简单地将fd 作为struct file_operations 数组的索引,并调用相应元素的.ioctl。内核永远不需要知道函数本身是什么,它指的是哪个设备。

    这是“一切都是文件”的基础,这是 Unix 的 moto。

    【讨论】:

    • 谢谢。我知道这是一个函数指针。但是用户空间中的泛型ioctl在哪里实现以正确选择file_operations数组中的函数?
    • @Amumu,它根本 不在 用户空间中。用户空间ioctl 只是调用ioctl 系统调用,传入参数。它是内核空间中的通用ioctl,它查看struct file_operations的数组。
    • @Shabaz 我将用户应用程序中通常使用的ioctl 称为用户空间ioctl。是的,我知道它在内核空间中选择了适当的ioctl。但是,我想知道内核空间中的通用ioctl 在哪里实现。我搜索了一下,它只给出了3个定义,所有这3个定义都是ioctl的驱动程序:lxr.free-electrons.com/ident?i=ioctl
    • 也许看看fs/ioctl.c 可能会让你有所收获!我不了解用户空间 ioctl。据我所知,它们是内核空间实现。如果用户空间有这种东西,需要在glibc中搜索ioctl的实现。
    • 这可能是一个很好的提示。我将尝试研究 glibc。我已经查看了fs/ioctl.c,但仍然找不到与接受文件描述符的相同ioctl 接口完全相同的定义。
    【解决方案3】:

    当您调用ioctl 时,您传递了一个文件描述符。你通过打开像/dev/tty0这样的设备文件获得了文件描述符:

    $ ls -l /dev/tty0
    crw--w---- 1 root tty 4, 0 Mar  6 10:47 /dev/tty0
    $
    

    这里的数字4 是设备主编号,它被编码到内核必须使用的驱动模块中。

    【讨论】:

    • 你知道它在内核代码的哪个位置根据 fd 选择合适的设备ioctl 吗?
    【解决方案4】:

    由于文件描述符,内核将知道要调用哪个ioctl 函数。 为了能够从用户空间调用 ioctl(),您必须打开一个文件以获取 fd,通常是 /dev/[some_device],正如您所指出的,它的驱动程序将实现 file_operations 结构。

    【讨论】:

      猜你喜欢
      • 2011-03-21
      • 1970-01-01
      • 2013-05-08
      • 2021-05-19
      • 2019-01-29
      • 2018-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多