0

我正在为我的应用程序使用 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 参数关联的真实代码在哪里。请你帮助我好吗?

4

1 回答 1

1

使用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 源代码结构类似。编辑:添加了一些文档指针。

于 2015-06-15T05:13:17.810 回答