반응형
Notice
Recent Posts
Recent Comments
관리 메뉴

꿈꾸는 사람.

[Android memory management] OOM killer vs LMK 본문

IT/Android

[Android memory management] OOM killer vs LMK

현무랑 니니 2014. 8. 6. 03:38
반응형









이번 글은 Android memory management 개요이다.

안드로이드는 Linux kernel을 사용하므로 메모리 관리에 linux kernel memory management 모듈인 OOM (Out of memory) killer를 그대로 사용하며, 안드로이드 메모리 관리 모듈인 LMK (Low memory killer)를 추가로 적용한다.


먼저 OOM과 OOM killer에 대해 알아보고 LMK를 설명한다.



1. OOM (Out of memory)

OOM이란 프로그램이나 운영체제에서 사용할 메모리를 할당하지 못하는 컴퓨터 동작 상태이다.

리눅스는 MMU란 하드웨어를 이용하여 가상메모리를 물리메모리로 변환하여 사용한다.

또한 리눅스는 demand paging를 사용하여 메모리 요청할 때 바로 할당하지 않고 실제 사용할 때 MMU에서 발생한 예외를 처리하여 메모리를 할당하는 방법이다.


가상 메모리로 사용하므로 물리 메모리보다 큰 메모리를 할당할 수 있는데 프로그램 사용 중 메모리를 할당할 때 가용 메모리를 넘어서면 Out of memory가 발생한다.



2. OOM killer

OOM 상황이 발생할 때 OOM killer가 여유 메모리를 확보하기 위해 아래와 같이 동작한다.

- 메모리가 부족할 때 직관적 알고리즘으로 나머지 시스템에 이득이 되도록 죽일 프로세스를 찾는다.

보다 많은 메모리를 반환할 수 있는 프로세스가 우선 선택된다.

- 중요 프로세스가 죽지 않도록 /proc/<pid>/oom_adj 값을 설정할 수 있다.

- oom_adj 값의 범위는 -17~ +15이다. 프로세스가 -17 (OOM_DISABLE)값을 가지면 OOM killer가 죽이지 않는다.

- oom_adj 값이 클수록 쉽게 죽을 수 있다. 


소스

include/uapi/linux/oom.h

#define OOM_SCORE_ADJ_MIN (-1000)

#define OOM_SCORE_ADJ_MAX 1000


#define OOM_DISABLE (-17)


mm/oom_kill.c

제거할 최적의 후보 프로세스를 찾기 위해 아래와 같이 badness() 함수가 호출된다.

 pagefault_out_of_memory-> out_of_memory() -> select_bad_process() -> badness()


badness() 함수

기능: 조사한 각 프로세스의 점수를 축적하고 이를 select_bad_process()함수로 반환한다.


1단계:  프로세스의 메모리 크기가 일차적인 점수가 된다.

/* * The memory size of the process is the basis for the badness. */ points = mm->total_vm;


2단계: 커널 스레드를 제외한 모든 자식 프로세스의 독립적 메모리 크기가 점수에 추가된다.

... if (child->mm != mm && child->mm) points += child->mm->total_vm/2 + 1;


3단계: 'Niced'프로세스는 점수가 증가하고, 오래 실행 중인 프로세스는 점수가 감소한다.

if (cpu_time) points /= int_sqrt(cpu_time); if (run_time) points /= int_sqrt(int_sqrt(run_time));


/* * Niced processes are most likely less important, so double * their badness points. */ if (task_nice(p) > 0) points *= 2;


4단계: CAP_SYS_ADMIN 및 CAP_SYS_RAWIO를 가진 프로세스는 점수를 감소한다.

if (has_capability_noaudit(p, CAP_SYS_ADMIN) || has_capability_noaudit(p, CAP_SYS_RESOURCE)) points /= 4;


if (has_capability_noaudit(p, CAP_SYS_RAWIO)) points /= 4;


5단계: 마지막으로 누적 점수는 /proc/<PID>/oomadj의 사용자 설정 값으로 bitshifted된다.

/* * Adjust the score by oomkilladj. */ if (p->oomkilladj) { if (p->oomkilladj > 0) { if (!points) points = 1; points <<= p->oomkilladj; } else points >>= -(p->oomkilladj); }


3. LMK (Low memory killer)

도입 배경

Linux kernel의 OOM killer가 android의 주요 서비스나 어플리케이션을 죽일 수 있는 문제를 보완하여, Android는 가용 메모리가 설정된 6개의 임계치 이하로 떨어지면 해당 그룹 별로 프로세스를 죽이도록 설정되어 있다.

즉, LMK는 OOM killer 동작 전에 여유 메모리를 확보하는 안드로이드에서 추가된 모듈이다.


동작 절차

어플리케이션은 자신의 상태(adj)를 항상 가지고 있는다. (/proc/<pid>/oom_adj) 6개의 메모리 임계값(minfree)으로 단계별로 메모리 문제를 다룬다. 어플리케이션의 상태 변화를 인지하여 어플리케이션 상태를 수정한다. adj과 minfree 값은 짝을 이룬다. (529, 24576) (1000, 30720) minfree값 이하로 메모리가 남은 경우 adj 값 이상의 어플리케이션을 제거한다. adj 값이 높을 수록 먼저 제거되고 다음 단계는 가상 메모리 양을 비교한다.


소스 분석

processlist.java - adj, minfree 값을 갱신 한다.

if (write) { writeFile("/sys/module/lowmemorykiller/parameters/adj", adjString.toString()); writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString()); }


명령 행에서

adj, minfree 값을 확인 한다.

# cat /sys/module/lowmemorykiller/parameters/adj 0, 58, 117, 176, 529, 1000 # cat /sys/module/lowmemorykiller/parameters/minfree 12288, 15360, 18432, 21504, 24576, 30720

minfree는 PAGE 단위로 표시되며 실제 용량은  [48, 60, 72, 84, 96, 120 (MB)]이다.



adj, minfree 값을 갱신한다.

# echo “0, 42, 128, 176, 520, 1000” > /sys/module/lowmemorykiller/parameters/adj # echo "1536,2048,4096,5120,15360,23040" > /sys/module/lowmemorykiller/parameters/minfree



반응형
Comments