Sha*_*rki 1 c linux memory-management
只是一个简单的问题(我希望如此)。如何通过 mlock 分配地址空间,然后在该空间内启动应用程序?
例如,我有一个从配置环境的包装程序启动的二进制文件。我只能访问包装器代码,并且希望在某个地址空间中启动二进制文件。可以从包装器中执行此操作吗?
谢谢!
如果您有程序的源代码,请添加命令行选项,以便程序mlockall(MCL_CURRENT | MCL_FUTURE)在某个时刻调用。这会将其锁定在内存中。
如果你想控制内核加载程序的地址空间,你需要深入研究内核内部。最有可能的是,没有理由这样做;只有拥有真正时髦硬件的人才会这样做。
如果您没有源代码,或者不想重新编译程序,那么您可以创建一个执行命令的动态库,并通过LD_PRELOAD.
将以下内容另存为lockall.c:
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
static void wrerr(const char *p)
{
if (p) {
const char *q = p + strlen(p);
ssize_t n;
while (p < q) {
n = write(STDERR_FILENO, p, (size_t)(q - p));
if (n > 0)
p += n;
else
if (n != -1 || errno != EINTR)
return;
}
}
}
static void init(void) __attribute__((constructor));
static void init(void)
{
int saved_errno = errno;
if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
const char *errmsg = strerror(errno);
wrerr("Cannot lock all memory: ");
wrerr(errmsg);
wrerr(".\n");
exit(127);
} else
wrerr("All memory locked.\n");
errno = saved_errno;
}
Run Code Online (Sandbox Code Playgroud)
liblockall.so使用以下命令将其编译为动态库
gcc -Wall -O2 -fPIC -shared lockall.c -Wl,-soname,liblockall.so -o liblockall.so
Run Code Online (Sandbox Code Playgroud)
例如,将库安装在典型的地方
sudo install -o 0 -g 0 -m 0664 liblockall.so /usr/lib/
Run Code Online (Sandbox Code Playgroud)
这样你就可以运行任何二进制文件,并将其锁定到内存中,使用
LD_PRELOAD=liblockall.so binary arguments..
Run Code Online (Sandbox Code Playgroud)
如果您将库安装在其他位置(未在 中列出/etc/ld.so.conf),则需要指定库的路径,例如
LD_PRELOAD=/usr/lib/liblockall.so binary arguments..
Run Code Online (Sandbox Code Playgroud)
Cannot lock all memory: Cannot allocate memory.通常,当以普通用户身份运行命令时,您会看到插入的库打印的消息。(超级用户或 root 通常没有这样的限制。)这是因为出于显而易见的原因,大多数 Linux 发行版都会限制非特权用户可以锁定到内存中的内存量;这就是RLIMIT_MEMLOCK 资源限制。运行ulimit -l以查看当前设置的每个进程资源限制(显然是针对当前用户)。
我建议您为进程可以运行的内存量设置一个合适的限制,ulimit -l 16384如果以超级用户(root)身份运行,则在执行之前运行例如 bash-built-in (将限制设置为 16384*1024 字节,或 16 MiB)。如果进程泄漏内存,而不是使您的机器崩溃(因为它锁定了所有可用内存),SIGSEGV如果超出限制,进程将会死亡(来自 )。也就是说,您将使用以下命令开始您的流程
ulimit -l 16384
LD_PRELOAD=/usr/lib/liblockall.so binary arguments..
Run Code Online (Sandbox Code Playgroud)
如果使用 Bash 或 dash shell。
如果作为专用用户运行,大多数发行版都会使用pam_limits.soPAM 模块“自动”设置资源限制。使用此格式/etc/security/limits.conf在文件或子目录中的文件中列出限制;该项指定每个进程可以锁定的内存量,以 1024 字节为单位。因此,如果您的服务以 user 身份运行,并且您希望允许用户锁定每个进程最多 16 MB = 16384*1024 字节,则将行添加到或中,无论您的 Linux 发行版喜欢/建议哪个。/etc/security/limits.d/memlockmydevmydev - memlock 16384/etc/security/limits.conf/etc/security/limits.d/mydev.conf
在 PAM 之前,shadow-utils用于控制资源限制。memlock资源限制以1024字节为单位指定;将使用设置 16 兆字节的限制M16384。因此,如果使用 Shadow-utils 而不是 PAM,添加行mydev M16384(后跟您希望指定的任何其他限制)应该可以/etc/limits解决问题。