前提条件
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()
吗?