fuz*_*fuz 11 memory posix setrlimit
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 兼容性。