c - 如何转发/多路复用 ioctl 组?

标签 c linux kernel ioctl

我正在尝试在 drm 内核中添加我自己的 ioctl。我已经有以下内容:

static struct drm_driver my_driver = {
//stuff
.ioctls = my_ioctls,
};

然后我有:

struct drm_ioctl_desc my_ioctls[] = {
// other stuff
DRM_IOCTL_DEF_DRV(MYIOCTL1, myfuncptr, myflags),
DRM_IOCTL_DEF_DRV(MYIOCTL2, myfuncptr2, myflags),
DRM_IOCTL_DEF_DRV(MYIOCTL3, myfuncptr3, myflags),
DRM_IOCTL_DEF_DRV(MYIOCTL4, myfuncptr4, myflags),
}

但是我如何将一组 ioctl 多路复用,并让它们在可能会或可能不会被编译的另一个文件/子文件夹中处理?

即我不想在 my_ioctls 结构中定义额外的 ioctls,因为如果使用某个配置,它们可能会调用未定义的函数。有没有办法在其他地方定义它们并在这种情况下处理它们?

谢谢! (我对此有些陌生,我想我了解基础知识,但我可能会忽略一些东西。)

最佳答案

一种可能的方法(粗鲁,更干净的解决方案见下文)是通过在调用特定于 drm 的设备分配器(例如 drm_dev_alloc)之前立即合并两个不同的表来构建一个 ioctl 表。这两个表来自不同的驱动程序部分并包含不同的服务子集。可选部分可能依赖编译器宏来创建表的完整版本或“ stub ”(空)版本。这是一个非常棘手的解决方案,而且肯定容易出错。基本上,鉴于这两个表,您必须

1) 将每个表导出为“外部”(或者至少是“可选”表)。我们称它们为 t1t2。注意:出于我们的目的,这些表不能定义为 const

2) 还导出两个 size_t 变量,其中包含两个表的“sizeof”(比方说 s1s2): size_t s1 = sizeof(t1)size_t s2 = sizeof(t2))

3) 在驱动程序初始化之前,确定两个表中最大的一个并将其指针分配给 struct drm_driverioctls 字段。该表将成为合并的“目标”。当然,struct drm_driver 也必须是非const。 您还必须相应地调整 num_ioctls 字段。

4) 通过复制具有非 NULL func 字段的每个元素来合并目标中的第二个表。要测试的元素数量是 sX/sizeof(struct drm_ioctl_descr),其中 sX 是第二个表的大小(即 s1 如果目标是 t2 s2 如果目标是 t1)。

5) 现在您可以照常注册驱动程序了。

好的,现在是一个更干净和“标准”的解决方案:

在“简化”版本中,将所有可选的 ioctls 实现为始终返回 -EINVAL-EOPNOTSUPP 的函数。唯一的缺点是,在您的表中,您始终必须提供所有服务(即使是尚未实现的服务)。

关于c - 如何转发/多路复用 ioctl 组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21466524/

相关文章:

linux - 如何将 Python 脚本的输出带到 Linux 中的前台/后台?

regex - sed 命令行 将 "aas=aas"更改为 "aas = aas"

linux - gcc 添加了哪些调试信息?

c - scanf() 在最终使用时陷入困境

c - 返回 x,其中从位置 p 开始的 n 位设置为 y 的最右边 n 位,其他位保持不变

c - scanf中短指针地址如何工作

c++ - 错误 LNK2001 : unresolved external symbol _D3DX10CreateTextureFromFileW@24

swift - Mac OS : Show custom column in finder for files like name, 大小等。

debugging - 我应该使用 Windbg_x86 在 64 位 Windows 中调试 32 位应用程序吗?

Linux 内核 rb 树