cgroup: memory 서브시스템

memory 서브시스템(memcg)은 프로세스 그룹의 메모리 리소스를 효율적으로 관리하는 기능이다. 이를 통해 메모리 사용량을 제한하고, Out-of-Memory(OOM) 상황을 방지할 수 있다. 또한 메모리 사용량 모니터링을 통해 리소스 사용 상태를 파악할 수 있으며, 메모리 압출 및 Swap 설정을 통해 메모리 최적화를 할 수 있다.

메모리 제한 설정

프로세스 그룹에 할당되는 메모리의 양을 제한할 수 있다. 이를 위해 memory.limit_in_bytes 파일을 사용한다.

  • /sys/fs/cgroup/memory/[cgroup_name]/memory.limit_in_bytes:
    • 프로세스 그룹에 할당되는 최대 메모리 양을 바이트 단위로 설정
    • 예를 들어, 1GB는 1,073,741,824로 표기

메모리 제한 설정 예시:

$ echo 1073741824 > /sys/fs/cgroup/memory/example_group/memory.limit_in_bytes

메모리 사용량 모니터링

memcg는 프로세스 그룹의 메모리 사용량을 모니터링할 수 있다. memory.usage_in_bytes 파일을 통해 사용량을 확인할 수 있으며, 바이트 단위로 표시된다. 예를 들어, 536870912는 512MB를 의미한다.

메모리 사용량 확인 예시:

$ cat /sys/fs/cgroup/memory/example_group/memory.usage_in_bytes

메모리 Threshold 설정

memcg 서브시스템은 cgroups notification API를 사용하여 메모리 threshold 를 구현한다. 이를 통해 이를 통해 메모리 및 메모리 Swap Threshold 를 등록하고, 이를 넘을 때 알림을 받을 수 있다.

메모리 Threshold를 등록하는 방법은 다음과 같다.

  • eventfd(2)를 사용하여 eventfd를 생성한다.
  • memory.usage_in_bytes 또는 memory.memsw.usage_in_bytes 를 연다.
  • “<eventfd> <memory.usage_in_bytes의 fd> <threshold>” 같은 문자열을 cgroup.event_control에 write한다.

메모리 사용량이 등록한 Threshold 값을 넘게되면, eventfd를 통해 notify된다. 애플리케이션은 이를 통해 threshold에 대한 action을 취할 수 있다.

Example:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/eventfd.h>

#define CGROUP_PATH "/sys/fs/cgroup/memory/example_group/"
#define THRESHOLD_VALUE 1073741824 // 1GB

int main() {
    // Create eventfd
    int event_fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
    if (event_fd == -1) {
        perror("Failed to create eventfd");
        return 1;
    }

    // Open memory.usage_in_bytes
    char usage_path[256];
    sprintf(usage_path, "%s/memory.usage_in_bytes", CGROUP_PATH);
    int usage_fd = open(usage_path, O_RDONLY);
    if (usage_fd == -1) {
        perror("Failed to open memory.usage_in_bytes");
        return 1;
    }

    // Open cgroup.event_control
    char event_control_path[256];
    sprintf(event_control_path, "%s/cgroup.event_control", CGROUP_PATH);
    int event_control_fd = open(event_control_path, O_WRONLY);
    if (event_control_fd == -1) {
        perror("Failed to open cgroup.event_control");
        return 1;
    }

    // Register threshold
    char event_control_str[256];
    sprintf(event_control_str, "%d %d %lu", event_fd, usage_fd, THRESHOLD_VALUE);
    if (write(event_control_fd, event_control_str, strlen(event_control_str)) == -1) {
        perror("Failed to write to cgroup.event_control");
        return 1;
    }

    printf("Threshold registered successfully\n");

    // Wait for event
    uint64_t event_value;
    if (read(event_fd, &event_value, sizeof(event_value)) == -1) {
        perror("Failed to read eventfd");
        return 1;
    }

    printf("Threshold crossed\n");

    // Close file descriptors
    close(event_fd);
    close(usage_fd);
    close(event_control_fd);

    return 0;
}

OOM (Out-of-Memory) 제어

memcg 서브시스템은 OOM 상황에서의 동작을 제어할 수 있다. OOM 상황은 시스템의 메모리가 부족한 상황에서 발생하며, 이를 효과적으로 관리하기 위해 memory.oom_control 파일을 사용한다.

  • /sys/fs/cgroup/memory/[cgroup_name]/memory.oom_control:
    • OOM 상황에서 프로세스 그룹의 동작을 제어
    • 0으로 설정하면 OOM 상황에서 프로세스를 종료시킨다.

OOM 제어 설정 예시:

$ echo 0 > /sys/fs/cgroup/memory/example_group/memory.oom_control

메모리 압축 및 스왑 설정

cgroup Memory 서브시스템은 메모리 압축과 스왑을 제어할 수 있다. 메모리 압축은 더 많은 데이터를 메모리에 저장하는 기술이며, 스왑은 메모리 부족 상황에서 디스크 공간을 사용하여 메모리를 보조하는 기술이다. 이를 제어하기 위해 memory.swappiness파일을 사용한다.

  • /sys/fs/cgroup/memory/[cgroup_name]/memory.swappiness:
    • 스왑 사용 정도를 설정하는 파일
    • 0은 스왑을 사용하지 않음을 의미하고, 100은 스왑을 최대한 사용함을 의미

메모리 압축 및 스왑 설정 예시:

$ echo 50 > /sys/fs/cgroup/memory/example_group/memory.swappiness

cgroups: 프로세스 그룹의 자원 관리
cgroup: cpu 서브시스템
cgroup: memory 서브시스템
cgroups: Memory Threshold Notifier 구현
cgruops v1 사용법

참고:

답글 남기기