안드로이드 메모리 관리 기술 자료

Linux System Memory Model


MMU(Memory Management Unit) 사용으로 인해 Physical Memory가 아닌 Virtual Memory로 동작함.
    – 현재 32bit ARM 아키텍처로 인해 Virtual memory 4GB 를 사용함.
    – 통상 User space 를 3GB, Kernel Space를 1GB를 사용
    – User space (0x0000 000 ~ 0xBFFF FFFF)
        프로세스가 사용자 모드에서 동작 중일 때의 어드레스로 프로세스가 사용자 모드이든 커널 모드이든 접근가능.
        application, library, stack, heap등 맵핑
    – Kernel space (0xC000 0000 – 0xFFFF FFFF)
        프로세스가 커널 모드에서 동작 중일때의 어드레스로, 프로세스가 커널 모드에서만 접근 가능.
        kernel, device driver, gpio 등 맵핑
    – Linux에서 각 프로세스가 할당받는 4GB의 가상 메모리를 실제 Physical memory로 맵핑하는 테이블과 관리자가 MMU


Virtual memory system architecture

ARM process
    – ARM core : 37~40개의 레지스터가 존재
    – MMU
    – Cache : 자주쓰는 메모리를 Virtual memory를 통하지 않고 물리메모리에 직접 억세스
    – Co-processor

Privileged mode, 특권 모드
    – 시스템 리소스를 마음대로 변경하기 위한 모드.
Non-privileged mode, 비 특권 모드
    – 불필요한 시스템 리소스의 접근을 제한하기 위해 사용한다.
    – User mode 만 Non-privileged mode 이다.

Operating mode의 변경
    – Reset, IRQ, SWI 등 exception이 발생하면 privileged mode로 변경된다.
    – OS를 사용하는 환경에서 user process 수행 시 일반적으로 SWI를 통한 시스템 콜을 사용하여 Privileged(SVC) mode로 전환한다.


MMU의 주요기능
    – 동적인 가상<–>물리 주소 변환을 가능하게 한다
    – 접근 권한 등 세분화된 메모리 관리가 가능하다.
    – 영역별로 캐시 사용을 지정할 수 있다.

프로세스 페이지 테이블
    – 가상주소의 구분
        – User space (0x0000 000 ~ 0xBFFF FFFF)
            프로세스가 사용자 모드에서 동작 중일 때의 어드레스로 프로세스가 사용자 모드이든 커널 모드이든 접근가능.
            application, library, stack, heap등 맵핑
        – Kernel space (0xC000 0000 – 0xFFFF FFFF)
            프로세스가 커널 모드에서 동작 중일때의 어드레스로, 프로세스가 커널 모드에서만 접근 가능.

    – PAGE_OFFSET 매크로
        가상주소 공간에서 커널 영역이 시작되는 오프셋으로 0xc000 0000 을 나타냄
        
페이징 관련 자료구조
    프로세스 주소 공간 (c program)
    0xFFFF FFFF
        커널 공간
    0xC000 0000
        Stack
        Memory Mapping Segment: 공유 라이브러리(xxx.so)
        Heap
        BSS (초기화 되지 않은 변수)
        Data (초기화 된 변수)
        Text

안드로이드에서 출력되는 메모리 주소는 Virtual memory address 이므로 실제 데이터는 Physical memory address를 봐야 한다!!


Linux의 OOM(Out Of Memory) Killer 문제

    응용 프로그램이 사용하는 가상 주소 공간의 크기가 시스템의 물리 주소보다 커질 수 있음.
    응용 프로그램은 시스템의 물리 메모리량을 고려하지 않고, 임의의 큰 주소공간 요청을 할당할 수 있음
    가용 메모리보다 큰 메모리 할당요청(malloc()) 사용시 항상 성공
    할당 메모리 접근시 fault 발생 !!
    OOM Killer 가 제거
    
Android Kernel 영역: Low memory killer
    Process 그룹당 우선 순위를 주어, 우선 순위가 낮은 그룹의 프로세스를 한꺼번에 해제
    그룹당 우선 순위는 init.rc에 정의
    App group 및 메모리 설정
        Foreground app            0
        Visible app                    1
        Secondary server        2        (Service daemon)
        Backup app                2
        Home app                    4        (시작화면에 등록되는 앱)
        Hidden app                7
        Content Provicer        14
        Empty app                    15
    
    Low memory killer 가 동작할 때 계산되는 score 값에 영향을 주는 값
    숫자가 높을 수록 low memory killer에 의해 죽을 가능성이 높음.
    절대 죽지않는 값을 -16으로 정의 ex> init process


Dalvik VM 메모리 할당
    각 프로세스 별 DVM이 별도 할당, heap size는 디바이스에 의해 조정되는 build-time 상수
    각 DVM은 각각의 heap을 가지고 있다
    Dalvik heap의 기본 크기는 16M로 max(48M)에 도달하면 시스템에 의해 kill 된다.
    동적할당함수 – mspace_calloc(), mspace_free()
    힙사이즈크기 – ActivityManager.getMemoryClass()
    
    만일 heap-limits를 변경하고자 한다면 달빅의 startup scripts 를 변경할 수 있다.
    한 프로세스에서 사용 가능한 멀티스레드 개수는 제한이 없으나 안드로이드에서 설정된 스레드 풀을 사용하는 AsyncTask를 권장한다.
    
GC의 기본 동작
    객체 제거 목록을 참조하여 삭제 시도
    Soft Reference, Weak Reference, Phantom Reference 사용하여 참조가능
    Ginger bread 이전에는 GC 수행시 app의 모든 thread 가 중지
    GB에서 GC는 concurrent 하게 작동하여 스레드를 중단 하지 않는다 (<5ms)
    각 프로세스마다 자신의 고유한 heap memory가 있으며, 프로그램이 실행 될 때 heap memory의 크기는 Dalvik이 정한다.
    현재 할당된 heap memory가 android에서 정한 concurrentStartBytes 보다 크면 바로 GC 시작
        app에서 할당할 수 있는 최대 heap 메모리 값(freeBytes)이 256KB 보다 작으면 concurrentStartBytes = 256KB
        그 외에는 concurrentStartBytes = freeBytes – 128KB 를 할당. (남은 heap size에서 128KB를 뺀 값)
    Android GC는 Mark and sweep 알고리즘을 사용한다.
        각 메모리 영역에 mark를 위해 1bit 메모리를 남겨 둔다.
        변수가 reference 하는 영역을 used라고 mark 한다. used가 표시되지 않는 영역을 접근 불가한 object라고 한다.
        Sweep step : 접근 불가한 영역을 모두 해제한다.
        포인터 조작에 오버헤드가 없으며 적은 공간을 소모한다.
        GC동안 잠시 멈춘다. 마킹중에 모든 노드를 방문한다.

GC heap
    자바 객체 등이 할당 된다.
    GC에 의하여 객체등이 적절한 시점에 해제된다.
Native heap
    JNI native method 가 malloc()을 사용할 때
    이미지 등을 사용할 때 (OutOfMemoryError: bitmap size exceeds VM budget 에러는 이미지에 의한 메모리 누수가 원인)


메모리 관련 adb shell 명령어
    cat /proc/meminfo : 시스템 메모리 사용 현황
        VSS(Virtual Set Size) : 프로세스와 관련된 Virtual memory 크기
        RSS(Resident Set Size) : 프로세스와 관련된 Physical pages 수 (공유 페이지 수 포함)
    procrank
        USS(Unique Set Size) : 프로세스만의 고유한 페이지 수 (공유되지 않은 크기)
        PSS(Proportional Set Size) : USS + (공유페이지/공유 프로세스 수)
    dumpsys meminfo [pid]
        프로세스가 사용하는 native(C/C++) 과 dalvik(JAVA) 영역을 구분하여 메모리 크기를 확인

Post Author: TORTUGA

TORTUGA
궁금하신 점은 새로 개편한 홈페이지의 QnA 게시판을 이용해주세요!!!!!!! http://www.hardcopyworld.com/gnuboard5/bbs/board.php?bo_table=qna

댓글 남기기

이메일은 공개되지 않습니다.