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

时间:2014-05-20 19:46:48

标签: memory posix setrlimit

Prequisites

POSIX.1 2008 specifies 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 defines 数据段是这样的:

  

3.125数据段

     

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

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

问题

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

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

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

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

  • 这违反了POSIX.1 2008吗?

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

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

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

1 个答案:

答案 0 :(得分:2)

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兼容性。