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变体吗?
答案 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兼容性。