POSIX rlimit: 我们对RLIMIT_DATA有哪些确切的假设?

13

前提条件

POSIX.1 2008 规定了 setrlimit()getrlimit() 函数。为resource参数提供了各种常量,以下部分是为更好地理解我问题而重复的一些内容。

以下资源已定义:

(...)

RLIMIT_DATA

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

(...)

RLIMIT_STACK

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

RLIMIT_AS

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

此外,POSIX.1 2008 定义了数据段

3.125 数据段

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

我知道RLIMIT_DATA资源传统上用于表示使用brk()函数为进程分配的最大内存量。最近的POSIX.1版本不再指定此函数,许多操作系统(例如Mac OS X)也不支持此函数作为系统调用。相反,它采用了mmap()的变体进行模拟,该函数不属于POSIX.1 2008。

问题

我对RLIMIT_DATA资源的语义和使用有些困惑。以下是我具体提出的问题:

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

  • 标准关于RLIMIT_DATA的说明:“如果超过此限制,则malloc()函数应失败,并将errno设置为[ENOMEM]。”这是否意味着由malloc()分配的内存必须是数据段的一部分?

    在Linux上,使用mmap()分配的内存不计入数据段。只有使用brk()sbrk()分配的内存属于数据段。最新版本的glibc使用分配所有内存的mmap()实现的malloc()。因此,RLIMIT_DATA的值对您可以使用此实现的malloc()分配的内存量没有影响。

  • 这是否违反了POSIX.1 2008规范?

  • 其他平台是否也有类似的行为?

    标准关于RLIMIT_AS的说明:“如果超过此限制,则malloc()和mmap()函数应失败,并将errno设置为[ENOMEM]。”由于对于RLIMIT_DATA未指定mmap()的失败情况,因此我得出结论,从mmap()获得的内存不计入数据段。

  • 这个假设是正确的吗?它只适用于非POSIX变体的mmap()吗?

  • 1个回答

    4

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

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

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


    1
    很遗憾听到这个消息。请注意,RLIMIT_VMEM也会影响不消耗RAM的mmap()文件。在64位机器上,您可以无问题地mmap()多TB文件,甚至不会消耗太多RAM(特别是如果文件是稀疏的)。因此,今天没有有效限制进程消耗实际内存量的方法... - fuz

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接