在Android 的ril.cpp中文名可以看到關乎RIL初始化流程第一個--建立基於event隊列的消息循環,可以接受上層發來的的請求。
該流程的主要函數RIL_startEventLoop().
該函數主要創建一個以eventlopp為入口的dispatch線程。下面是該函數的代碼:
extern "C" void
RIL_startEventLoop(void) {
int ret;
pthread_attr_t attr;
/* spin up eventLoop thread and wait for it to get started */
s_started = 0;
pthread_mutex_lock(&s_startupMutex);
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
while (s_started == 0) {
pthread_cond_wait(&s_startupCond, &s_startupMutex);
}
pthread_mutex_unlock(&s_startupMutex);
if (ret < 0) {
LOGE("Failed to create dispatch thread errno:%d", errno);
return;
}
}
pthread_mutex_lock(&s_startupMutex)與pthread_mutex_unlock(&s_startupMutex)之間是線程的創建,加鎖與解鎖是為了多線程的沖突。
pthread_attr_init (&attr)與 pthread_create()為線程的創建,在創建時 pthread庫會自動地為線程設定棧大小,我們通常不用明顯地指定。當發生了內存分配不足時,就必須我們自已動手來指定棧大小。這裡我們可以看到eventLoop的入口。
在創建之前初始化線程,我們可以利用pthread_attr_getstacksize來得到默認分配大小,注意到必須先調用pthread_attr_init初始化函數,才能得到正確的值,否則得到的值是不正確的。 其中用pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)來使線程達到detach狀態。
這裡就是dispatch線程的創建過程。
開始分析Android源代碼中的RIL部分。
又上圖,以及其他相關資料,我得知在Android中有一個叫rild的守護進程。我猜測此進程與電話的撥打接聽有莫大關系。
而且在Android系統中存在這麼一個rild的可執行文件,源代碼中的"hardware/ril/rild"目錄下有rild.c的文件 ,且在rild.c中,我們找到了main函數,即我們已經找到了rild守護進程的程序入口啦~
自贊一個先~
開始分析rild守護進程的代碼。
在代碼開始部分,有一些關於參數解析的片段,暫時先撇開一邊,先講一下rild守護進程的關於RIL的一些重要流程:
main()
{//省略n行
RIL_startEventLoop();
//省略n行
}
從名字上看就應該覺得這應該是一個起點——"startEventLoop"——一個開始進入時間循環的一點,讓我們跟蹤進去看看^_^
在"rild.c"中有這麼一行:extern void RIL_startEventLoop();
說明RIL_startEventLoop函數的代碼還在別處,經查找,發現是在這裡:
"hardware\ril\libril"目錄下的Ril.cpp文件中。
Get it~
在Ril.cpp中的RIL_startEventLoop中有這麼一行:
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
看來Android是在這裡開辟一個線程來執行eventLoop循環,
這個eventLoop函數也在這個文件裡(Ril.cpp)。
eventLoop中,主要執行了:
ril_event_init();
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
processWakeupCallback, NULL);
ril_event_add (&s_wakeupfd_event);
ril_event_loop();
由函數名可猜測:
ril_event_set使用了新建一個ril事件的,
而ril_event_add 將該新事件添加進某執行隊列中。
最後,在循環ril_event_loop中進行一個輪詢,捕獲事件,進而完成事件處理。
經過對ril_event_set和ril_event_add的代碼閱讀,證實了之前的兩點猜測,
(ril_event_set和ril_event_add以及ril_event_loop函數代碼在"hardware\ril\libril"目錄下的ril_event.cpp中)
新事件加入了一個叫watch_table的數組中。
而 ril_event_loop則調用了一個select函數,目前還在分析該函數中~~(猜測是unix類系統的系統調用,暫時先放過)
重新從eventloop的流程開始分析起:
首先,是那個ril_event_init函數。ril_event_init函數在Ril_event.cpp("hardware\ril\libril"),Ril_event.cpp中有一個timer_list的ril_event結構體,這個結構體充當待處理的事件隊列(I guest)
而ril_event_init就是在做事件隊列的初始化工作(通過init_list(&timer_list),當然還有另外還初始化了pending_list)
然後,就是ril_event_set一個事件結構s_wakeupfd_event
接著,就是ril_event_add該s_wakeupfd_event結構體添加到Ril_event.cpp的watch_table數組中。
最後就是執行ril_event_loop循環了。
請注意,以上步驟中並沒有將事件添加到事件隊列(timer_list)中的部分,但是ril_event_loop的運作就是要基於timer_list的,那事件隊列不是空的嗎?怎麼會這樣呢?
在查看了相關代碼之後,發現了有一個叫ril_timer_add的函數執行了addToList函數,即猜測應該是某個函數調用了ril_timer_add?是什麼函數呢?通過用Source Insight查找函數的caller,發現了internalRequestTimedCallback函數調用了ril_timer_add。從名字我想起了關鍵一點:當前流程只是用來“處理”電話事件而已,並不是自己生成一個電話事件啊,電話事件應該是由此流程外的對象生成的(比如有來電了,又如要打電話了),用中斷來進行事件隊列的事件添加。
到此為止,我們已經確認了rild的主要監聽功能就是在ril_event_loop中:
其中在ril_event_loop的for (;;)循環中,我們看到了if (-1 == calcNextTimeout(&tv)),這裡就是在嘗試處理電話事件啦^_^。