我试图阻止学生代码在分配中运行,并拖延我的测试机器.我试过了
setrlimit(RLIMIT_DATA, r);
Run Code Online (Sandbox Code Playgroud)
哪个r
是持有限制的结构.但不幸的是,虽然这个限制停止brk
并且sbrk
分配,但是C库只是故障转移mmap
并保持正确分配.
我也试过了
setrlimit(RLIMIT_AS, r)
Run Code Online (Sandbox Code Playgroud)
并且这会使进程停止,但是这种补救措施太严重了 - 进程无法从ENOMEM
错误中恢复,因为代码在遇到NULL
返回的值时所进行的调用没有堆栈空间malloc()
.
我对二进制文件的控制有限,所以如果可以用系统调用,我宁愿这样做.但我需要一些方法来限制分配,而不会破坏流程的恢复能力.有没有人有建议?
更新:我找到了一个名为failmalloc的东西,但它不是很复杂,虽然我可以导致它失败,但我总是遇到gdb无法诊断的段错误.
进一步更新:我发现setrlimit(RLIMIT_AS, r)
它似乎做我想要的工作,至少在被不相关的模块中发生的故障之后引起了某些情况下,该段错误.除非有人想出一些有趣的东西(或保留问题的理由),否则我可能会删除这个问题.
在下面的给出示例中,我尝试将stacksize设置为1kb.
为什么现在可以在堆栈中分配一个大小为8kb
in 的int数组foo()
?
#include <stdio.h>
#include <sys/resource.h>
void foo(void);
int main() {
struct rlimit lim = {1024, 1024};
if (setrlimit(RLIMIT_STACK, &lim) == -1)
return 1;
foo();
return 0;
}
void foo() {
unsigned ints[2048];
printf("foo: %u\n", ints[2047]=42);
}
Run Code Online (Sandbox Code Playgroud) 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()
吗?
我写了一个简单的程序来限制它的数据大小为65Kb,并验证相同我分配一个超过65Kb的虚拟内存,逻辑上如果我正在做所有正确(如下)malloc调用应该失败,不是吗?
#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main (int argc, char *argv[])
{
struct rlimit limit;
/* Get max data size . */
if (getrlimit(RLIMIT_DATA, &limit) != 0) {
printf("getrlimit() failed with errno=%d\n", errno);
return 1;
}
printf("The soft limit is %lu\n", limit.rlim_cur);
printf("The hard limit is %lu\n", limit.rlim_max);
limit.rlim_cur = 65 * 1024;
limit.rlim_max = 65 * 1024;
if (setrlimit(RLIMIT_DATA, &limit) != 0) {
printf("setrlimit() failed with errno=%d\n", errno);
return 1;
}
if (getrlimit(RLIMIT_DATA, &limit) != …
Run Code Online (Sandbox Code Playgroud) 我试图setrlimit
限制我在Linux系统上的内存使用,以阻止我的进程崩溃机器(我的代码崩溃了高性能集群上的节点,因为一个错误导致内存消耗超过100 GiB ).我似乎无法找到传递给他的正确资源setrlimit
; 我认为它应该是常驻的,不能用setrlimit限制,但我对常驻,堆,堆栈感到困惑.在下面的代码中; 如果我只取消注释RLIMIT_AS
,代码将失败MemoryError
,numpy.ones(shape=(1000, 1000, 10), dtype="f8")
即使该数组应该只有80 MB.如果我只取消注释RLIMIT_DATA
,RLIMIT_RSS
或RLIMIT_STACK
两个阵列获得成功分配,即使总内存使用量为2 GB,或两次所需的最大.
我想让我的程序一旦尝试分配太多RAM就失败(无论如何).为什么所有的RLIMIT_DATA
,RLIMIT_RSS
,RLIMIT_STACK
和RLIMIT_AS
做什么,我的意思是,什么是正确的资源传递给setrlimit
?
$ cat mwe.py
#!/usr/bin/env python3.5
import resource
import numpy
#rsrc = resource.RLIMIT_AS
#rsrc = resource.RLIMIT_DATA
#rsrc = resource.RLIMIT_RSS
#rsrc = resource.RLIMIT_STACK
soft, hard = resource.getrlimit(rsrc)
print("Limit starts as:", soft, hard)
resource.setrlimit(rsrc, (1e9, 1e9))
soft, hard = resource.getrlimit(rsrc)
print("Limit is now:", soft, …
Run Code Online (Sandbox Code Playgroud) 有没有办法遍历已经打开的文件描述符(由父进程打开)并在子进程中一一关闭它们?
操作系统:Unix。
关闭原因:setrlimit() 的 RLIMIT_NOFILE 限制限制了一个进程可以分配的文件描述符的数量。如果我们想通过设置这个限制来限制我们的子进程,它取决于已经分配的文件描述符。
尝试在子进程中设置此限制是受到限制的,因为父进程有一些打开的文件描述符,因此我们不能将此限制设置为小于该数字。
示例:如果父进程分配了 10 个文件描述符,并且我们希望将子进程文件描述符数量限制为小于 10(比如 3),我们将需要关闭子进程内的 7 个文件描述符。
对此的解决方案可以使所有想要限制其子进程创建新文件或打开新网络连接的人受益。
在*NIX系统上,有没有办法找出当前运行过程中有多少个打开的文件句柄?
我正在寻找一个在C中使用的API或公式,从正在运行的进程中.
我正在编写一个需要处理许多开放套接字的服务器,所以我setrlimit()
用来设置打开文件描述符的最大数量(以root身份,在删除权限之前),如下所示:
#include <sys/resource.h>
#define MAX_FD_C 9001
if (setrlimit(
RLIMIT_NOFILE, &(struct rlimit){.rlim_cur = MAX_FD_C, .rlim_max = MAX_FD_C}
) == -1) {
perror("Failed to set the maximum number of open file descriptors");
return EXIT_FAILURE;
}
Run Code Online (Sandbox Code Playgroud)
现在,我意识到可能没有任何保证,并且我受Linux内核用于实现文件描述符表的任何方法的支配; 但实际上,假设这个程序从Linux内核收到的任何fd的值都小于我在上面设置的MAX_FD_C,这是否合理?
我想每个插槽的数据,以保持尽可能的紧凑它可以简单地使用像数组是指static struct client clients[MAX_FD_C] = {{0}};
与使用FD作为索引到客户端结构(这基本上是我自己的版本的FDT的).
是否有可能在WinAPI中为运行时的当前线程设置堆栈大小,就像setrlimit
在Linux上一样?我的意思是增加当前线程的保留堆栈大小,如果它对于当前要求来说太小了.这是一个可以被其他编程语言的线程调用的库,因此在编译时不能选择设置堆栈大小.
如果没有,任何关于像汇编蹦床这样的解决方案的想法会将堆栈指针更改为动态分配的内存块?
常见问题:代理线程是一个万无一失的解决方案(除非调用者线程的堆栈非常小).但是,线程切换似乎是性能杀手.我需要大量的堆栈用于递归或_alloca
.这也是为了提高性能,因为堆分配很慢,特别是如果多个线程并行地从堆中分配(它们被相同的libc
/ CRT
互斥锁阻塞,因此代码变为串行).
我想增加我的C程序可用的最大文件描述符数,该程序在OSX 10.7上运行.我已将以下代码添加到我的项目中,但它失败了!
struct rlimit limit;
if(getrlimit(RLIMIT_NOFILE, &limit))
{
perror("Failed to get limit");
return -1;
}
printf("%llu, %llu\n", limit.rlim_cur, limit.rlim_max);
limit.rlim_cur *= 4;
printf("%llu, %llu\n", limit.rlim_cur, limit.rlim_max);
if(setrlimit(RLIMIT_NOFILE, &limit))
{
perror("Failed to set limit");
return -1;
}
Run Code Online (Sandbox Code Playgroud)
它打印日志:
4864, 9223372036854775807
19456, 9223372036854775807
Failed to set limit: Invalid argument
Run Code Online (Sandbox Code Playgroud)
最大限制似乎有点太高了.这是怎么回事?
对于一个进程,我为资源设置了软限制值335544320
和硬限制值。即使设置了这个值,进程的地址空间也会上升到最大值。但是我能够看到正确设置为上述值的软限制和硬限制的值。1610612736
RLIMIT_AS
178MB
/proc/process_number/limits
我想知道是否RLIMIT_AS
在我的操作系统中工作,还想知道如何测试该RLIMIT_AS
功能。
CentOS 5.5(64 位)是我使用的操作系统。
有些人请帮我解决这个问题。谢谢!
我试图用来setrlimit()
限制一个过程花费的时间.但是,当我执行某些操作时,它似乎不起作用printf()
.
这是一个说明问题的测试程序:
#include <sys/resource.h>
#include <stdio.h>
int main(void) {
int i;
struct rlimit limit;
limit.rlim_cur = 3;
limit.rlim_max = 3; // send SIGKILL after 3 seconds
setrlimit(RLIMIT_CPU, &limit);
// doesn't get killed
for(i=0; i<1000000; i++)
printf("%d",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我用一个不同的例程替换for循环,比如天真的斐波那契:
int fib(int n) {
if(n<=1) return 1;
return fib(n-1)+fib(n-2);
}
int main(void) {
...
fib(100);
...
}
Run Code Online (Sandbox Code Playgroud)
它完美地运作.这里发生了什么?是setrlimit()
根本不可靠?