1

我试图通过 io_uring_register_buffers() 注册一组缓冲区,但我无法注册足够大的缓冲区。一个大于 32768 字节的缓冲区或几个总大小大于 32768 的缓冲区都会导致 ENOMEM 错误。我读过一个缓冲区的最大缓冲区大小为 1GB。

有一个例子:

#include <stdlib.h>
#include <stdio.h>
#include <liburing.h>

#define LEN 4096
#define CNT 9

int main()
{
    struct io_uring ring;
    struct iovec iov[CNT];
    char *buf;
    int res;

    if (io_uring_queue_init(64, &ring, 0) != 0)
        return -1;

    buf = malloc(LEN*CNT);

    for (int i = 0; i < CNT; i++) {
        iov[i].iov_base = buf + (i * LEN);
        iov[i].iov_len = LEN;
    }

    res = io_uring_register_buffers(&ring, iov, CNT);
    printf("%d\n", res);

    io_uring_queue_exit(&ring);

    return 0;
}

如果我将 CNT 定义为 9,则会出现 ENOMEM 错误。怎么了?

4

2 回答 2

0

我认为另一种选择是分配和注册一个大缓冲区,然后只需在提交队列条目中的缓冲区中提供偏移量。

于 2021-07-04T19:27:37.550 回答
0

我从一个自由的贡献者那里得到了答案。

Pavel Begunkov(沉默):

你点击了 RLIMIT_MEMLOCK。限制通常为 64KB,但我猜你偶然发现了 32KB,因为 malloc 返回一个未对齐的块,但注册适用于页面,因此对于每个缓冲区它注册 2 个相邻页面,这是两倍。

在我的系统中,非特权用户的硬限制是 64kB。使用aligned_alloc(4096, LEN CNT) 而不是malloc(LEN CNT),我有64kB 的限制。

所以至少有两种方法:

  1. 在系统设置中为非特权用户增加 RLIMIT_MEMLOCK;
  2. 以root用户身份执行程序。
于 2021-06-16T11:26:03.763 回答