【问题标题】:Limit physical memory per process限制每个进程的物理内存
【发布时间】:2011-10-16 11:52:59
【问题描述】:

我正在编写一个算法来执行一些外部内存计算,即您的输入数据不适合主内存并且您必须考虑 I/O 复杂性。

由于我的测试并不总是想要使用真实输入,我想限制我的进程可用的内存量。我发现,我可以设置mem内核参数来限制所有进程的物理使用内存(对吗?)

有没有办法做到这一点,但有一个每个进程的限制。我见过ulimit,但它只限制了每个进程的虚拟内存。有什么想法(也许我什至可以在我的 C++ 代码中以编程方式设置它)?

【问题讨论】:

  • 您是依靠虚拟内存和linux的分页将相关数据加载到内存中,还是打算自己手动将数据加载到缓冲区中?
  • 我使用虚拟内存 + linux 的分页(加上一个名为 stxxl 的库用于一些外部内存数据结构,但我已经可以控制它们的内存使用)
  • 添加了 linux-kernel 标签,因为您可能需要为此直接与内核交谈,而内核人员最有可能知道它。

标签: c++ linux memory process linux-kernel


【解决方案1】:

正如其他发帖者已经指出的那样,setrlimit 是最可能的解决方案,它控制了流程环境的所有可配置方面的限制。使用此命令查看您的 shell 进程中的这些单独设置:

ulimit -a

结果输出中与您的场景最相关的内容如下:

data seg size           (kbytes, -d) unlimited
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
virtual memory          (kbytes, -v) unlimited

查看 setrlimit ("man setrlimit") 的手册页,它可以通过您的 C/C++ 代码以编程方式调用。我过去曾使用它来控制堆栈大小限制,效果很好。 (顺便说一句,ulimit 没有专门的手册页,它实际上是一个嵌入式 bash 命令,所以它在 bash 手册页中。)

【讨论】:

    【解决方案2】:

    您可以尝试使用“cgroups”。 要使用它们,请以 root 身份输入以下命令。

    # mkdir /dev/cgroups
    # mount -t cgroup -omemory memory /dev/cgroups
    # mkdir /dev/cgroups/test
    # echo 10000000 > /dev/cgroups/test/memory.limit_in_bytes
    # echo 12000000 > /dev/cgroups/test/memory.memsw.limit_in_bytes
    # echo <PID> > /dev/cgroups/test/tasks
    

    您要添加到 cgroup 的进程的 PID 在哪里。请注意,该限制适用于分配给此 cgroup 的所有进程的总和。

    从现在开始,进程被限制为 10MB 的物理内存和 12MB 的 pysical+swap。

    该目录中还有其他可调参数,但具体列表取决于您使用的内核版本。

    您甚至可以创建限制层次结构,只需创建子目录。

    cgroup 是在你 fork/exec 时继承的,所以如果你将启动程序的 shell 添加到 cgroup 中,它将自动分配。

    请注意,您可以将 cgroup 挂载到任何您想要的目录中,而不仅仅是 /dev/cgroups。

    【讨论】:

    • 我应该能够使用/proc/&lt;pid&gt;/statusVmHWM 条目来验证是否满足限制,对吧?
    • 我不确定这是否如此简单。将 /proc//status 与 cgroups/*/memory.usage_in_bytes 进行比较,它们有些不同。也许与共享内存或虚拟与物理内存有关...我认为cgroups仅限制进程请求的新内存,但不考虑在进程添加到cgroup之前存在的共享内存。请参阅文档here
    • 接受这个答案:cgroups 为我工作。 -omemory 是错字吗(没有空格)?无论如何,我发现相应地设置 cgconfig 并直接在 cgroup (cgexec) 中启动我的进程更舒服,例如jlebar.com/2011/6/15/…
    • 没有错字,实际上,空格是可选的,虽然它看起来会更好。
    【解决方案3】:

    您是否考虑过在某种虚拟环境中尝试您的代码?虚拟机可能无法满足您的需求,但 User-Mode Linux 之类的东西可能更合适。这会将 linux 内核作为常规操作系统中的单个进程运行。然后您可以提供单独的mem= 内核设置,以及单独的交换空间来进行受控实验。

    【讨论】:

      【解决方案4】:

      内核mem= 引导参数限制了整个操作系统将使用多少内存。

      这几乎不是用户想要的。

      对于物理内存,有 RSS rlimit aka RLIMIT_AS

      【讨论】:

      【解决方案5】:

      我会使用带有 RLIMIT_AS 参数的 setrlimti 来设置虚拟内存的限制(这是 ulimit 所做的),然后让进程使用 mlockall(MCL_CURRENT|MCL_FUTURE) 来强制内核出错并锁定到物理 RAM所有进程页面,因此该进程的虚拟量 == 该进程的物理内存量

      【讨论】:

      • mlockall 确实有问题。除了在某些情况下您确实想限制物理内存并享受交换(例如,桌面应用程序)之外,某些编程语言(例如,golang 或 java)使用 mmap+PROTO_ANON 分配大量虚拟空间,所以您不能使用它们。而且即使你使用 C++,你也无法使用 asan 之类的东西。
      • (请注意我实际上认识给出答案的人,小世界......)
      【解决方案6】:

      我无法提供直接的答案,但关于做这些事情,我通常会编写自己的内存管理系统,这样我就可以完全控制内存区域和分配的数量。当您为微控制器编写代码时,这通常也适用。希望对您有所帮助。

      【讨论】:

      • +1 用于跟踪您自己的内存使用情况的简单方法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 2016-03-09
      • 2011-01-24
      • 2018-11-01
      • 2018-03-30
      • 2013-07-29
      • 1970-01-01
      相关资源
      最近更新 更多