나는 빨간 모자 기계를 사용하고 있습니다. sysctl을 통해 max_map_count 값을 변경하고 있습니다.
# sysctl vm.max_map_count
vm.max_map_count = 65530
# sysctl -w vm.max_map_count=655300
vm.max_map_count = 655300
# sysctl vm.max_map_count
vm.max_map_count = 655300
/etc/sysctl.conf
그런 다음 재부팅 후에도 유지되도록 해당 값을 작성합니다 .
나는 특정 장기 서비스의 문맵 요구 사항을 해결하기 위해 이 작업을 수행했습니다. 내가 아는 한, sysctl 값을 변경하는 것은 시스템에 즉시 적용됩니다. 내 질문은: 이 업데이트된 설정을 특정 실행 프로세스에 적용하려면 개별 서비스를 다시 시작해야 합니까, 아니면 업데이트된 개수 제한이 실행 중인 프로세스에 즉시 적용됩니까?
답변1
아래 프로그램을 실행해 보니 프로세스를 다시 시작할 필요가 없다는 것을 알았습니다. 즉, max_map_count 설정은 모든 프로세스에 즉시 적용됩니다.
(나는 -에서왔다https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/mem/tunable/max_map_count.c#L171다음을 작성하십시오. 라이센스는 GPLv2 이상입니다. )
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include <unistd.h>
const char* MAX_MAP_PROC_FILE = "/proc/sys/vm/max_map_count";
/* This is a filter to exclude map entries which aren't accounted
* for in the vm_area_struct's map_count.
*/
static bool filter_map(const char *line)
{
char buf[BUFSIZ];
int ret;
ret = sscanf(line, "%*p-%*p %*4s %*p %*2d:%*2d %*d %s", buf);
if (ret != 1)
return false;
#if defined(__x86_64__) || defined(__x86__)
/* On x86, there's an old compat vsyscall page */
if (!strcmp(buf, "[vsyscall]"))
return true;
#elif defined(__ia64__)
/* On ia64, the vdso is not a proper mapping */
if (!strcmp(buf, "[vdso]"))
return true;
#elif defined(__arm__)
/* Skip it when run it in aarch64 */
if ((!strcmp(un.machine, "aarch64"))
|| (!strcmp(un.machine, "aarch64_be")))
return false;
/* Older arm kernels didn't label their vdso maps */
if (!strncmp(line, "ffff0000-ffff1000", 17))
return true;
#endif
return false;
}
static long count_maps(pid_t pid)
{
FILE *fp;
size_t len;
char *line = NULL;
char maps_proc_name[BUFSIZ];
long map_count = 0;
snprintf(maps_proc_name, BUFSIZ, "/proc/%d/maps", pid);
fp = fopen(maps_proc_name, "r");
if (fp == NULL) {
fprintf(stderr, "Could not open proc file: %s\n", maps_proc_name);
exit(1);
}
while (getline(&line, &len, fp) != -1) {
/* exclude vdso and vsyscall */
if (filter_map(line))
continue;
map_count++;
}
fclose(fp);
return map_count;
}
static void update_max_map()
{
FILE *fp = fopen(MAX_MAP_PROC_FILE, "w");
if (fp == NULL) {
fprintf(stderr, "Could not open proc file: %s\n", MAX_MAP_PROC_FILE);
exit(1);
}
fprintf(fp, "%d", 655300);
fclose(fp);
}
static void map_and_print_count()
{
int num_lines = 0;
while (mmap(NULL, 1, PROT_READ, MAP_SHARED | MAP_ANONYMOUS, -1, 0) != MAP_FAILED)
{
}
printf("mmap failed with errno: %s\n", strerror(errno));
num_lines = count_maps(getpid());
printf("number of lines: %d\n", num_lines);
}
int
main(int argc, char* argv[])
{
int num_lines = 0;
num_lines = count_maps(getpid());
printf("number of lines to start: %d\n", num_lines);
map_and_print_count();
update_max_map();
map_and_print_count();
return 0;
}
이 명령을 실행하면 다음과 같은 출력이 생성됩니다.
# gcc -Wall -o max_map_count max_map_count.c && ./max_map_count
number of lines to start: 16
mmap failed with errno: Cannot allocate memory
number of lines: 65531
mmap failed with errno: Cannot allocate memory
number of lines: 655301
max_map_count를 업데이트한 후 프로세스는 이제 프로세스가 실행되는 동안 지정된 수의 맵을 얻을 수 있습니다.