Linux 6.18 memory·cgroup v2 · AOSP lmkd 문서

메모리가 남아 보이는데도 할당이 실패하는 이유

가상 주소, 물리 메모리, 연속 공간, cgroup 제한과 Android lmkd를 구분합니다.

한 가지 “남은 메모리” 숫자로는 설명할 수 없습니다

질문확인할 대상
프로세스의 주소 공간이 부족합니까?가상 주소 배치·mapping·rlimit·ABI 폭을 봅니다.
사용 가능한 물리 메모리가 부족합니까?회수 가능한 cache·anonymous memory·swap·zone 상태 등을 봅니다.
큰 연속 공간이 필요합니까?총량뿐 아니라 fragmentation·할당 order·CMA 등 요청 조건을 봅니다.
그 작업에 허용된 한도를 넘었습니까?cgroup·컨테이너·서비스에 적용된 제한을 봅니다.

malloc이 성공했다고 그 크기만큼 모든 물리 페이지를 즉시 독점 확보했다는 뜻은 아닙니다. 실제 page fault와 사용 과정, overcommit 정책에 따라 시점이 다를 수 있습니다. 반대로 free 메모리가 조금 있다고 어떤 GFP 조건의 kernel 할당도 성공하는 것은 아닙니다. 가상 메모리와 page 회수 page 할당 조건

호스트 전체와 내 cgroup의 여유는 다를 수 있습니다

cgroup v2에서는 memory.current로 사용량을 보고 memory.max 등의 제한을 확인합니다. memory.high는 주로 회수·throttling 경로를 유도하는 경계이며 memory.max와 같은 hard limit로 읽으면 안 됩니다. memory.events의 high·max·oom·oom_kill 등의 변화도 의미가 다릅니다. cgroup v2 memory controller

cat /proc/meminfo
cat /proc/self/cgroup
cat /sys/fs/cgroup/example/memory.current
cat /sys/fs/cgroup/example/memory.events

example은 실제 cgroup 경로로 바꾸는 관찰 예입니다. cgroup v1이나 mount 구성에 따라 파일이 다릅니다. 컨테이너 안에서 보이는 경로와 호스트 경로도 구분해야 합니다.

Android lmkd와 kernel OOM killer는 같은 코드가 아닙니다

메모리 압박을 조사할 때 구분할 경로
  1. 메모리 압박 관측

    회수 지연·pressure·사용량·한도 등을 관찰합니다.

    어느 정책 주체가 반응했는지 확인합니다.

  2. 정책과 선택

    kernel의 OOM 처리인지 Android lmkd의 선택인지 구분합니다.

    해당 주체의 로그와 선택 기준을 확인합니다.

  3. 프로세스 종료 또는 실패

    어떤 process·cgroup이 영향을 받았는지 확인합니다.

    원래 allocation·workload·제한과 연결합니다.

  4. 원인 정리

    누수·과도한 buffer·한도·재현 조건을 비교합니다.

화살표는 조사 순서입니다. 모든 메모리 압박이 반드시 OOM kill로 이어진다는 뜻은 아닙니다.

Android lmkd는 사용자 공간 daemon이며 Android의 process 중요도와 memory pressure 정보를 활용합니다. 옛 lowmemorykiller kernel driver 설명을 최근 모든 Android 기기에 그대로 적용하지 않습니다. 특정 앱이 종료됐다는 사실만으로 Java heap의 OutOfMemoryError와도 동일시하지 않습니다. Android lmkd의 동작

원인을 정한 뒤 할당과 수명을 고칩니다

문제수정 방향을 정할 증거
누수 의심요청 반복 후 살아 있는 객체·buffer 수가 계속 증가하는지 확인합니다.
순간적인 peak여러 pipeline이 겹치는 시점과 buffer 개수를 확인합니다.
연속 공간 문제요청 크기·order·DMA 요구 조건과 실제 fragmentation을 확인합니다.
cgroup 제한애플리케이션의 요구량과 의도한 서비스 한도를 대조합니다.

무조건 cache를 비우거나 OOM 대상 선택 값을 바꾸는 것으로 원인을 덮지 않습니다. 해제 후에도 device·worker가 buffer를 쓰는 문제는 누수를 줄이려다 use-after-free로 바뀔 수 있으므로 수명부터 맞춰야 합니다.