我正在为我的应用程序使用 Infiniband 驱动程序的 OFED 3.18r2 实现。特别是我正在使用 rdma 连接管理器包装函数。为了更好地理解幕后发生的事情,我习惯于查看源代码。这样做我发现了一些看起来像模式的东西,但我无法理解它。让我们举个例子。 rdma 连接管理器函数位于 cma.c 中。查看 rdma_listen 调用的示例(这对于库中定义的几乎所有以“rdma_”开头的函数来说都是常见的):
int rdma_listen(struct rdma_cm_id *id, int backlog)
{
struct ucma_abi_listen cmd;
struct cma_id_private *id_priv;
int ret;
CMA_INIT_CMD(&cmd, sizeof cmd, LISTEN);
id_priv = container_of(id, struct cma_id_private, id);
cmd.id = id_priv->handle;
cmd.backlog = backlog;
ret = write(id->channel->fd, &cmd, sizeof cmd);
if (ret != sizeof cmd)
return (ret >= 0) ? ERR(ENODATA) : -1;
if (af_ib_support)
return ucma_query_addr(id);
else
return ucma_query_route(id);
}
在这里你可以看到我之前提到的模式:
ret = write(id->channel->fd, &cmd, sizeof cmd);
write 调用的第一个参数是与 /dev/infiniband/rdma_cm 关联的文件描述符,但我无法理解 cmd 参数的用法。我深入研究源代码,却发现 cmd 是一个用于 rdma cm 函数调用的 ABI 定义的结构体。我真的不明白这是否是执行设备驱动程序调用的常见模式以及它是如何工作的,与 cmd 参数关联的真正代码在哪里。 你能帮我一下吗?
最佳答案
使用write()
系统调用来执行命令是在RDMA子系统中执行命令的常用方法。它由 rdma_ucm 模块和 ib_uverbs 模块等使用。与 rdma_ucm 相关的内核代码可以在 drivers/infiniband/core/ucma.c 中找到文件。具体来说,该设备的 write()
系统调用是在 ucma_write()
函数中实现的。
我认为关于这种调用驱动程序的方法没有很多文档。 user_verbs.txt
内核文档中的文档指出:
Commands are sent to the kernel via write()s on these device files.
The ABI is defined in drivers/infiniband/include/ib_user_verbs.h.
The structs for commands that require a response from the kernel
contain a 64-bit field used to pass a pointer to an output buffer.
Status is returned to userspace as the return value of the write()
system call.
我认为这可能是对 write()
系统调用的一个小滥用,它实现了更类似于 ioctl()
的东西。
编辑:请注意,我添加了到上游内核模块的链接,但 OFED 源结构是相似的。 编辑:添加了一些文档指针。
关于c - RDMA 连接管理器驱动程序模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30829021/