POSIX rlimit:我们对RLIMIT_DATA究竟有什么假设?

fuz*_*fuz 11 memory posix setrlimit

Prequisites

POSIX.1 2008 指定setrlimit()getrlimit()函数.为resource论证提供了各种常数,其中一些常规在下面复制,以便更容易理解我的问题.

定义了以下资源:

(......)

RLIMIT_DATA

这是进程数据段的最大大小(以字节为单位).如果超出此限制,则malloc()函数将失败,并将errno设置为[ENOMEM].

(......)

RLIMIT_STACK

这是初始线程堆栈的最大大小(以字节为单位).实现不会自动使堆栈超出此限制.如果超出此限制,则应为该线程生成SIGSEGV.如果线程阻塞SIGSEGV,或者进程忽略或捕获SIGSEGV并且没有安排使用备用堆栈,则SIGSEGV的处置应在生成之前设置为SIG_DFL.

RLIMIT_AS

这是进程总可用内存的最大大小(以字节为单位).如果超出此限制,则malloc()和mmap()函数将失败,并将errno设置为[ENOMEM].此外,自动堆栈增长失败,具有上述效果.

此外,POSIX.1 2008 定义了这样的 数据段:

3.125数据段

与进程关联的内存,可以包含动态分配的数据.

据我所知,该RLMIT_DATA资源传统上用于表示可以使用该brk()功能分配给进程的最大内存量.最新版本的POSIX.1不再指定此功能,许多操作系统(例如Mac OS X)不支持此功能作为系统调用.相反,它的模拟版本mmap()不属于POSIX.1 2008.

问题

我对RLIMIT_DATA资源的语义和使用有点困惑.以下是我的具体问题:

  • 根据此规范,堆栈是否可以成为数据段的一部分?

  • 该标准说,有关RLIMIT_DATA:"如果超过这个限制,malloc()函数的功能应errno设置为[ENOMEM]失败"这是否意味着与分配的内存malloc()必须是数据段的一部分?

    在Linux上,分配的内存mmap()不计入数据段.只有内存分配brk()或是sbrk()数据段的一部分.最新版本的glibc使用一个malloc()实现来分配其所有内存mmap().RLIMIT_DATA因此,这个值对使用此实现可以分配的内存量没有影响malloc().

  • 这违反了POSIX.1 2008吗?

  • 其他平台表现出类似的行为吗?

    该标准说RLIMIT_AS:"如果超出此限制,malloc()和mmap()函数将失败,并将errno设置为[ENOMEM]." 由于mmap()没有指定失败RLIMIT_DATA,我得出结论,从中获得的内存mmap()不计入数据段.

  • 这个假设是真的吗?这仅适用于非POSIX变体mmap()吗?

小智 4

FreeBSD 还存在在默认 malloc 实现中使用 mmap(2) 实现 malloc(3) 的问题。我在将产品从 FreeBSD 6 移植到 7 时遇到了这个问题,也就是发生了切换。我们将每个进程的默认限制从 RLIMIT_DATA=512M 更改为 RLIMIT_VMEM=512M,即将虚拟内存分配限制为 512MB。

至于这是否违反POSIX,我不知道。我的直觉是,很多东西都违反了 POSIX,而 100% 符合 POSIX 的系统就像严格确认的 C 编译器一样罕见。

编辑:呵呵,现在我发现 FreeBSD 的名称 RLIMIT_VMEM 是非标准的;他们将 RLIMIT_AS 定义为 RLIMIT_VMEM 以实现 POSIX 兼容性。