久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

淺析Android的RILD服務進程的消息循環(huán)

 mot0522 2013-02-21

淺析Android的RILD服務進程的消息循環(huán)  

2012-01-11 15:36:27|  分類: Android開發(fā) |  標簽:android  消息   |字號 訂閱

Android中,RILD是RIL(Radio Interface Layer) Deamon的簡稱,。簡單的說它下面承接GSM/GPRS Modem(電話通信模塊),,上面接電話應用相關的Java庫(telephony internal),。telephony internal通過socket將請求發(fā)送給RILD的消息循環(huán),消息循環(huán)則將請求轉發(fā)給底層通信模塊(直接調用底層的庫)來實現對通信模塊功能的調 用,。反之,,當通信模塊有類似于來電的消息時,也會通過RILD的回調,,將信息包裝成消息,,發(fā)送到RILD的消息循環(huán)中去處理,最后再通過socket回送 給telephony internal,,以便通知上層,。整體結構參見如下:


  • 概述 

        消息循環(huán)(ril_event_loop()函數內)位于單獨的線程中,用來處理三種消息,,分別對應三個不同的隊列,,面對的是三種不同的需求:
        1.定時列表(timer_list): 此隊列中的消息主要用于處理一些延時的操作。比如:從飛信模式切換到通信模式(實際上就是打開通信模塊)時,,若SIM卡未準備好,,那么需要延續(xù)一段時間再檢查是否準備好,此時就要將消息扔至此隊列,。
        2.偵聽列表(watch_list): 此隊列中的消息一是作為socket的服務端,,用來偵聽客戶端的請求;另一個是作為本進程的其它線程(如:檢查通信模塊來電消息的線程)傳遞過來的消息,。
        3.掛起列表(pending_list): 之所以叫掛起,,實際上指的是在處理上面兩中類型的消息時,并不真正的處理消息體,,而是將符合條件的消息丟到本隊列中,。由于消息附帶處理函數,所以在處理本隊列的消息時,,直接觸發(fā)即可,。
        消息循環(huán)所要做的事就是先等待某個時間間隔(定時消息要求的)或者是客戶端(socket或通訊模塊的消息)的請求,,然后再按次序處理上面三個對列中的消息,。

        下面還是通過源代碼來分析消息循環(huán)的處理過程。

  • ril_event

        ril_event指代的是消息,,它的數據結構如下:

  1. struct ril_event *next; // 下一個消息   
  2. struct ril_event *prev; // 前一個消息   
  3. int fd; // 開始我以為這里有可能是socket描述符或pipe描述符,,但實際上它還被用作消息的回調函數的參數?   
  4. int index; // 偵聽列表(watch_list)中的索引,,偵聽列表采用的數組而不是鏈表   
  5. bool persist; // 是否常駐偵聽列表(watch_list)中,。若常駐,則當被轉到pending_list中時,,不刪除,。   
  6. struct timeval timeout; // 超時,,這個為一個時間點。在處理定時消息時,,用于和當前的時間比較,,以確定是否處理該消息。   
  7. ril_event_cb func; // 回調,。此消息對應的處理函數,。   
  8. void *param; // 回調參數。  
        三種消息列表的定義如下:
  1. static struct ril_event * watch_table[MAX_FD_EVENTS]; // 偵聽列表   
  2. static struct ril_event timer_list; // 定時列表   
  3. static struct ril_event pending_list; // 掛起列表  
  • ril_event_init()

        初始化過程還是要從rild的main入口開始分析起,,位于文件hardware/ril/rild/rild.c,。簡單期間,只介紹本文相關的部分,。 main()函數會調用函數RIL_register(),,然后會調用RIL_startEventLoop()。 RIL_startEventLoop()中會創(chuàng)建線程eventLoop,,這個實際上就是rild的消息循環(huán)所在的線程,。

  1. ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);  
        eventLoop()首先會進行初始化:
  1. ril_event_init();  
        然后,會通過pipe()函數創(chuàng)建管道,。pipe()函數會創(chuàng)建一對文件描述符,,一個用于讀,另一個用于寫,。都被記錄在全局變量中,。它實際上是用來發(fā)送定時消息的,后面會介紹,。
  1. ret = pipe(filedes);  
  2. // ......   
  3. s_fdWakeupRead = filedes[0]; // 消息循環(huán)中偵聽   
  4. s_fdWakeupWrite = filedes[1]; // 用于通知消息循環(huán)定義消息已發(fā)送  
        最后一步就是進入消息循環(huán):
  1. // Only returns on error   
  2. ril_event_loop();  
  • ril_event_loop()

        ril_event_loop()中,,每次循環(huán)都主要做三件事:
        1.初始化。主要是獲取要等待的描述符,,以及獲取超時信息,,以便能夠及時處理定時消息。
        2.等待,。等待socket客戶端有新的消息,,或一定的時間間隔,之后處理定時消息,。
        3.依次處理三種類型的消息,。
        下面分別敘述之。先是獲取要等待的描述符,,這里為什么要這么做呢,?我的理解是在添加新的消息時,有可能會修改全局的描述符列表。也就是說,,全局的描述符列表有可能在本次循環(huán)的處理過程中發(fā)生變化,。

  1. // make local copy of read fd_set   
  2. memcpy(&rfds, &readFds, sizeof(fd_set));  
        接下來,就是計算select()函數的超時參數,。select的最后一個參數代表超時,。若為NULL,則select死等,;若為0,,則select立即返回;若大于0,,則限制了select最長的等待時間,。
  1. if (-1 == calcNextTimeout(&tv)) { // 獲取超時參數,若失敗則返回-1,。   
  2.     // no pending timers; block indefinitely   
  3.     dlog("~~~~ no timers; blocking indefinitely ~~~~");  
  4.     ptv = NULL;  
  5. else { // 獲取成功,,則使用該值。   
  6.     dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);  
  7.     ptv = &tv;  
  8. }  
        calcNextTimeout()函數先是判斷超時消息的列表是否為空,,為空則返回-1,;
  1. // Sorted list, so calc based on first node   
  2. if (tev == &timer_list) {  
  3.     // no pending timers   
  4.     return -1;  

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現有害或侵權內容,請點擊一鍵舉報,。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多