본문 바로가기

Linux/Android

[Android] OOM (Out of Memory) 와 LMK (Low Memory Killer) 이야기.

출처 : http://shadowxx.egloos.com/10781292


안녕하세요멀티미디어팀에 이상철입니다.

 

오늘은 여러분들이 프로젝트를 진행하면서 한번을 들어 볼(?) OOM (Out of Memory)  LMK (Low Memory Killer) 에 대한 이야기를 해볼까 합니다.

 

오늘 이야기는 예전에 제가 보내드렸던 "[Android] Background process 줄여서 Memory 확보로 성능 개선하기." 메일과 관련이 깊은 내용입니다.

 

사실 이번 이야기는 제 동기가 찾아서 보내준 내용을 제가 여러분들과 공유하고자 전송해드리는 정도입니다.

 

간단히 정리하면, OOM  Linux 커널에서 예전부터 쭈~욱 있어왔던 메모리 관리 모듈이고 이게 휴대기기에 들어가는 system 에서는 안맞다고 생각해서 OOM 이 일어나지 않도록 메모리를 관리하자라고 생각해서 Android 에서 만든게 LMK 입니다.

, Android 에는 LMK  OOM 이 다 있고 동작합니다하지만 OOM 이 발생되면 파급 효과(? - 아래 글을 읽어보면 이해가 되실 것입니다가 크기 때문에 미연에 이러한 것을 방지하고자 동작되는 것이 LMK 라고 보시면 됩니다.

 

아래는 제 동기 최종한 선임이 보내준 내용입니다.

======================================

Android memory management

0. OOM Killer
- linux kernel
의 메모리 부족시 메모리 확보를 하는 process
- src 
위치 : mm/oom_kill.c

기본 설명 :
시스템 구동중 메모리가 부족하면 운영체제 내부의 우선순위 알고리즘에 의해 프로세스를 죽인다.
리눅스 커널은 프로세스의 메모리 할당시 남은 메모리가 없는 상황을 처리하기 위해 OOM(Out of Memory) Killer 를 가지고 있다
그 것은 모든 프로세스를 어떤 제약으로 점수를 매겨 init을 제외한 최고 점수의 프로세스는 죽여 메모리를 확보한다.
따라서 일반적으로 서버를 운영할때에는 서비스데몬이 oom-killer에게 안죽도록 메모리관리를 잘해야한다

- Wiki OOM
most cases, a computer with virtual memory support where the majority of the loaded data resides on the hard disk would probably run so slowly due to excessive paging that it would be considered to have failed, 
prompting the user to close some programs or reboot. As such, an out of memory message is rarely encountered by applications with modern computers
The typical OOM case in modern computers happens when the operating system is unable to create any more virtual memory, because all of its potential backing devices have been filled. 
Operating systems such as Linux will attempt to recover from this type of OOM condition by terminating a low-priority process, a mechanism known as the OOM Killer


- OOM 
발생 원인
커널은 Virtual memory를 이용한 메모리 할당을 하므로 실제 가용한 physical 메모리 보다 큰 프로그램 size의 메모리를 할당 할 수 있다
즉 프로그램에서 당장 사용하지 않는 메모리는 나중에 메모리를 할당하기 때문에 실제 사용 가능한 메모리를 넘는process load될 수 있다.(이것을 overcommit 이라 한다.) 
만약 overcommit된 메모리에 실제 뭔가 쓰여지기 시작하면 메모리가 모자라므로 Out of memory가 발생한다.

- OOM Killer Configure
/proc/meminfo/CommitLimit : Commit Limit / SWAP + SOME REAL MEMORY
/proc/meminfo/Committed_AS : 
현재 Commited 된 양
/proc/sys/vm/overcommit_memory : (mode 0 - heuristic / mode 1 - always overcommit / mode 2 - strict overcommit, overcommit 
불가)
/proc/sys/vm/overcommit_ratio : The percentage can be more than 100, for a situation where you have lots of programs that don't use much of their allocated space.(percentage of real memory)

- Kill Policy
* The formula used is relatively simple and documented inline in the
* function. The main rationale is that we want to select a good task
* to kill when we run out of memory.
*
* Good in this context means that:
* 1) we lose the minimum amount of work done
* 2) we recover a large amount of memory
* 3) we don't kill anything innocent of eating tons of memory
* 4) we want to kill the minimum amount of processes (one)
* 5) we try to kill the process the user expects us to kill, this
* algorithm has been meticulously tuned to meet the principle
* of least surprise ... (be careful when you change it)

- Comment
기본적으로 OOM은 적은 수의 프로세스를 죽여서 많은 양의 메모리를 확보할 수 있는 heuristic을 쓰는 것을 알 수 있다.
OOM killer
 heuristic에 기반하고 있기 때문에중요한 server process가 죽지않는 다는 보장을 하기가 힘들다
하지만, OOM killer를 쓰지 않는다고 하더라도특정 프로세스가 종료할 때까지 기다리는 수 밖에 없고,
page fault handler
에서 page frame을 할당받지 못하면, init를 제외한 해당 task kill 되기 때문에, OOM 상황에서는 어차피 치명적인 상황이 발생한다.
따라서, OOM 상황이 발생하지 않도록 노력하는 것이 중요하여 이때문에 안드로이드에서는 별도로 LMK를 사용하고 있다.

- Reference site
http://blog.naver.com/PostView.nhn?blogId=pinocc&logNo=120059187934
http://blog.naver.com/newbeing2000/30036826720
http://lechuck.tistory.com/38
http://andstudy.springnote.com/pages/3667993

 

1. Low Memory Killer
안드로이드에 특화된 OOM
- src
위치 : /drivers/staging/android/lowmemorykiller.c(공식 커널에선 제외되어 안드로이드 커널에서만 볼 수 있다.)

기본설명
low memory killer
는 구글 직원이 2009년에 안드로이드 메모리 관리를 위해 작성한 리눅스 커널 모듈이다
이 커널이 등장한 배경은 리눅스 메모리 정책이 현재 임베디드 환경에 맞지 않다는 것이다
리눅스 커널의 기본 메모리 정책은 OOM Killer로 대표되는데 메모리가 부족한 상황에서 최대한의 가용성을 확보하기 위해 가상 메모리를 가장 많이 할당한 프로세스를 죽이는 형태로 되어 있다
이런 정책은 서버나 임베디드 환경에서 주요 서비스나 주요 어플리케이션을 죽일 수 있다.
안드로이드의 가용 RAM이 설정된 Threshold 이하로 떨어지게 되면 프로세스 중요성별로 분류된 6가지 그룹중 해당Application Kill 하도록 설정되어 있습니다.
그래서 시스템을 최종 사용자(end user) 관점에서 안정적이게 만든다

-Application
 6가지 타입으로 분류

- LMK Configure
# cat /sys/module/lowmemorykiller/parameters/adj
cat /sys/module/lowmemorykiller/parameters/adj
0,1,2,4,7,15
# cat /sys/module/lowmemorykiller/parameters/minfree
2048,3072,4096,6144,7168,8192
위 값은 4KB 페이지 단위로 표현된 것을 보여준 것이고, 4번째 값인 7168 HIDDNE_APP  Threshold에 해당
가용 RAM 7168 * 4K = 29M로 줄어들어야 HIDDEN_APP Kill 하도록 설정되어 있음
이 값은 /init.rc에 표기되어 있음


- Kill Policy
1. 
어플리케이션은 자신의 상태(adj)를 항상 가지고 있는다. (/proc/<pid>/oom_adj) 
2. 
운영체제는 몇개의 메모리 문턱(minfree)을 가지고 있어서 단계로 메모리 문제를 다룬다
3. 
운영체제는 어플리케이션의 상태 변화를 인지하여 어플리케이션 상태를 수정한다
4. adj
 minfree 값은 짝을 이룬다. (0, 1024) (8, 4096) 
5. minfree
값 이하로 메모리가 남은 경우 adj 값 이상의 어플리케이션을 제거한다. (4096 페이지 이하일 경우 adj  8이상의 어플리케이션 중 하나가 제거된다.) 
6. adj 
값이 높을 수록 먼저 제거되고 차순으로는 가상 메모리 양을 비교한다. (4096 페이지 이하일 때 8 10이 있을 경우 10이먼저 제거된다.) 
*3
번 과정인 어플리케이션 상태 수정은 유저 레벨 서비스인 ActivityManager가 변경한다
어플리케이션 상태는 GUI와 깊은 연관이 있기 때문에 커널 레벨에서 일방적으로 결정하기에는 부적절하다

- Reference
http://barriosstory.blogspot.com/2009/02/taming-oom-killer.html
http://s2junn.tistory.com/45
http://dalinaum-kr.tumblr.com/post/4528344482/android-low-memory-killer

 

이상입니다.