2016년 9월 18일 일요일

HeapWorker 동작 방식 분석(미완)

Android 2.2 기반의 heap worker 동작방식을 분석해 보았으나, 미완성이다-_-;


시스템에 의해 특정 어플이 시작될 때, zygote 프로세스가 fork되면서 ~ 언젠가는 exec로 dalvikvm 프로세스를 실행시킬 것으로 보인다.

dalvikvm/Main.c
int main(int argc, char* const argv[])

JNI_CreateJavaVM 함수를 실행시키는데, 인자로 넘기는 p_vm, p_env 는 NULL이 할당된 채로 넘겨진다. vm_args 에는 멤버변수에 값을 채운다. 





vm/Jni.c
jint JNI_CreateJavaVM(JavaVM** p_vm, JNIEnv** p_env, void* vm_args)

이 함수에서는 ./vm/Init.c 파일에 정의된 struct DvmGlobals gDvm 글로벌 변수를 초기화한다.
또한 JavaVMExt 구조체 포인터도 malloc하는데, 하나의 프로세스 내에서 사용되는 여러 개의 JNIEnvExt구조체들의 리스트를 들고있는 구조체다. 

dvmStartup함수를 호출한다.




vm/Init.c

int dvmStartup(int argc, const char* const argv[], bool ignoreUnrecognized, JNIEnv* pEnv)
dvmStartup 함수에서는 많은 컴포넌트들을 초기화 하는데, 목록은 다음과 같다. 
dvmAllocTrackerStartup
dvmGcStartup
     --> dvnHeapStartup --> dvmInitializeHeapWorkerState();
dvmThreadStartup
     --> gDvm.pthreadKeySelf 를 만든다. 각종 쓰레드 뮤텍스, condition 변수 생성 및 초기화, 
dvmInlineNativeStartup
dvmVerificationStartup
dvmRegisterMapStartup
dvmInstanceofStartup
dvnClassStartup
dvmThreadObjStartup
dvmExceptionStartup
dvmStringInternStartup
dvmNativeStartup
dvmInternalNativeStartup
dvnJniStartup
dvnReflectStartup
dvmProfilingStartup

각 종, 클래스 로드, hashtable생성 등등의 일을 한다.

쭉 초기화 진행 후,
gDvm.zygote 변수가 true면 dvmInitZygote() 함수를 호출하고, (zygote모드)
false이면 dvmInitAfterZygote()함수를 호출한다. (non-zygote모드)


bool dvmInitAfterZygote(void)
이 함수는, 새로이 프로세스가 만들어질 때 zygote fork 이후에 호출되어진다. 
가장 먼저 dvmGcStartupAfterZygote 함수를 호출한다. 





vm/alloc/Alloc.c

bool dvmGcStartupAfterZygote(void)
이 함수 하는 일은 dvmHeapWorkerStartup()함수 호출한다.






dalvik/vm/alloc/HeapWorker.c

bool dvmHeapWorkerStartup(void)
이 함수는 각 초기화 변수들이 제대로 세팅되어 있는지 체크 후,
heapWorkerLock 뮤텍스 변수에 lock을 걸고, dvmCreateInternalThread함수로 heapWorkerThreadStart 쓰레드함수를 시작시킨다.
dvmCreateInternalThread함수는 통상적인 pthread_create 를 수행하고,
바로, thread list 락을 건 다음, create상태를 체크한다. (pthread_cond_wait()함수는 락을 풀고 시그널을 받기 전까지 현재 쓰레드를 대기시킨다. 시그널을 받으면 다시 락을 건 다음 while문의 조건 검사를 하고 조건을 만족시키면 다음으로 넘어간다.)
그러니까, 쓰레드가 제대로 생성되었는지를 기다려준다는 것이다. 제대로 생성이 되었다면 heapWorkerLock 뮤텍스 락을 푼다.




static void* heapWorkerThreadStart(void* arg)
함수는 다음과 같이 동작한다.
처음 실행 시 초기화 수행에 대한 mutex condition 조건 및 lock 들을 풀어주고.
heapWorkerLock 뮤텍스 락을 건 다음,

haltHeapWorker 변수가 false인 동안 while문을 돈다.
1. dvm상태를 THREAD_VMWAIT로 변경하고,
2. heapWorkerIdleCond 뮤텍스컨디션 변수를 풀어주며 (해당 condition으로 wait상태인 다른 쓰레드가 깨어나도록)
3.



















댓글 없음:

댓글 쓰기