为什么Linux原始套接字的RX环限制为4GB?

问题描述 投票:1回答:2

背景

我正在尝试在我的64位Linux应用程序中mmap()原始套接字的RX环形缓冲区。我的戒指由4096块大小为1MB的块组成,总共4GB。 (注意每个1MB块中可以有很多帧.See this doc for background if you're curious.

问题

不幸的是,当使用带有选项setsockopt()PACKET_RX_RING进行配置时,RX环缓冲区的大小似乎有4GB的限制。对我来说,这意味着我不能再增加我的块大小或我的戒指尺寸。我的申请将受益于增加。

现在版本的Linux内核至少强制实施此限制。 See the source here.

(请注意,没有问题mmap()ing大于4GB。我最初偶然发现了this question。)

为什么RX环缓冲区的限制为4GB?如果从32位迁移内核的这部分内容时出现错误,那将很酷并且可能很容易进行修补。但是,如果有更根本的原因,我很想知道那可能是什么。

linux linux-kernel network-programming raw-sockets
2个回答
1
投票

这是一个错误。我提交了一个补丁修复此问题(现已合并):https://github.com/torvalds/linux/commit/fc62814d690cf62189854464f4bd07457d5e9e50


1
投票

这是部分答案。让我们来看看如何分配PACKET_MMAP环形缓冲区结构及其缓冲区。这是通过调用line 4270alloc_pg_vec完成的。结构本身只是一个指针数组,使用kcalloc进行分配,它的上限为131,072字节。如果每个指针的大小为8个字节,那么最多可以有131,072/8 = 16,384 = 214个块。每个块使用alloc_one_pg_vec_page分配。请注意,每个块在内存中必须是连续的,其大小必须是页面大小的倍数(4096字节)。传递给orderalloc_pg_vec参数表示每个缓冲区要分配为2的幂的页数。 mmzone.h中定义的顺序有一个限制,即MAX_ORDER = 11.因此,最大块大小为4096 * 211 = 223 = 8 MiB。这意味着整体环限制为237字节或128 GiB。

我不知道为什么检查req->tp_block_size > UINT_MAX / req->tp_block_nr被执行。这可能是因为早期版本的Linux支持较少数量的缓冲区和缓冲区大小(Linux 2.4中的MAX_ORDER为10)。但也许通过删除检查,您可以分配最大128 GiB的环。

© www.soinside.com 2019 - 2024. All rights reserved.