【问题标题】:LINUX: How to lock the pages of a process in memoryLINUX:如何锁定内存中进程的页面
【发布时间】:2012-09-20 20:33:16
【问题描述】:

我有一个 LINUX 服务器运行一个占用大量内存的进程(某种数据库引擎)。此进程分配的内存非常大,需要将其中的一部分换出(分页)。

我想做的是将所有其他进程(或正在运行的进程的子集)的内存页面锁定在内存中,以便只有数据库进程的页面被换出。例如,我想确保我可以继续远程连接并监控机器,而不会受到交换的影响。 IE。我希望 sshd、X、top、vmstat 等所有页面都驻留在内存中。

在 linux 上有 mlock()、mlockall() 系统调用,它们似乎提供了正确的旋钮来进行固定。不幸的是,在我看来,我需要在每个进程中进行显式调用,并且不能从不同的进程或父进程调用 mlock()(mlock() 不是在 fork() 或 evecve() 之后继承的)。

非常感谢任何帮助。提供虚拟披萨和啤酒 :-)。

【问题讨论】:

  • mlockall(2) 是一个非常非常非常糟糕的主意。 1.您需要对所有其他进程执行 munlockall 否则风险是OOM(但如果进程本身调用了mlockall,您不应该这样做)
  • 2.其他进程的数量是不同的。 3. 一些特殊的进程不能ptrace,否则会微妙地改变原程序的行为 -------------- 只需简单地使用cgroup来控制你的数据库RAM使用,或者使用systemd来管理它.

标签: linux swap


【解决方案1】:

我已经有一段时间没有这样做了,所以我可能错过了一些步骤。

制作一个包含如下内容的 GDB 命令文件:

call mlockall(3)
detach

然后在命令行中,找到你要mlock的进程的PID。类型:
gdb --pid [PID] --batch -x [command file]

如果您喜欢pgrep,那可能是:
gdb --pid $(pgrep sshd) --batch -x [command file]

【讨论】:

  • .......不要将这样的脚本放在任何用户都可以找到的地方...
  • @twalberg:除非用户是root,否则可以锁定的内存量是有限的。通常是64KB之类的小东西。在大多数 Linux 系统中,非 root mlock 都有一个 rlimit 设置,允许将其用于安全目的,例如将密码和加密密钥保留在交换文件之外,但不能用于拒绝服务攻击。
  • 仍然...... 100 个用户为他们的 50 个进程中的每一个保留 64KB 加起来......很多......也许没有一个用户可以导致 DOS,但累积效应可能是绝对负面的.
  • @twalberg:这需要所有 100 个用户都同意同时使用服务器。不太可能。
  • call (int) mlockall(1) 在测试块 i/o 对延迟的贡献方面为我工作。非常有效!
【解决方案2】:

实际上锁定系统上大部分内容的页面似乎有点粗鲁/激烈,更不用说这种机制的滥用似乎必然会导致一些其他意想不到的问题。

理想情况下,您可能真正想要的是控制进程组的“交换性”,以便数据库最先被交换,而基本的系统管理工具排在最后,there is a way of doing this

【讨论】:

  • 您好 Timday,您说的过于激烈是对的。内存 cgroup 似乎 正是 我需要的(至少乍一看,没有阅读所有文档)。很酷!我不知道存在这样的功能。谢谢!
  • 请注意,对于 cgroups v2(它正慢慢开始成为默认设置),还有memory.low(和memory.min)设置定义了不交换多少内存(如果可能) .不过,我不确定这是如何详细工作的。
【解决方案3】:

在搜索mlockall 信息时,我遇到了这个工具。您也许可以为您的发行版找到它。我只找到了手册页。

http://linux.die.net/man/8/memlockd

【讨论】:

  • 嗨赞,谢谢你的指点。据我了解, mlockall() 将文件锁定在内存中(而不是进程),但它是另一个可以派上用场的工具。再次感谢!
  • @pollol:你读过mlockall() 的手册页吗?它不是文件,它是进程内存。作为副作用,如果您将文件映射到内存并锁定它,它也会被锁定到缓存中。
  • 我的帖子在几个层面上都很糟糕。首先,我指的是 memlockd 而不是 mlockall()。其次,我想我误解了 memlockd 的手册页。它说:“将系统程序和配置文件锁定在内存中”。由此我了解到,程序的可执行文件加上其他库被锁定在缓存中,而不是进程的整个 RSS。
  • 以防万一有人读到这个:我检查了memlockds 源代码,它所做的只是将所有给定的进程可执行文件映射到内存mmap(),然后将该进程二进制文件锁定在内存中@987654327 @(相关源码:pastebin.com/t2csPhHP)。它不能替代mlockall()
【解决方案4】:

如今,解决这个问题的简单而正确的方法是 cgroup。

只限制数据库进程的内存使用:

1. create a memory cgroup
    sudo cgcreate -g memory:$test_db -t $User:$User -a $User:$User

2. limit the group's RAM usage to 1G. 
    echo 1000M > /sys/fs/cgroup/memory/$test_db/memory.limit_in_bytes
    or 
    echo 1000M > /sys/fs/cgroup/memory/$test_db/memory.soft_limit_in_bytes

3. run the database program in the $test_db cgroup
   cgexec -g memory:$test_db $db_program_name

【讨论】:

  • 不是答案,目的不是限制内存使用,而是让进程免于交换。
  • 当数据库进程被限制内存使用时(只有数据库进程会被换出),如果总内存足够,其他进程可以避免换出。
  • @peterh cgroup 有 softlimit 选项,这意味着如果系统可以满足其他进程的 RAM 要求,则进程(数据库)可以超出限制内存限制(例如 1G)。
猜你喜欢
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 2019-07-25
  • 1970-01-01
相关资源
最近更新 更多