android 視訊通話 專案 原始碼
阿新 • • 發佈:2019-01-08
Android Phone分析(三)
2010-01-27 17:51
分析初始化流程,主入口是rild.c中的main函式,主要完成三個任務:
1. 開啟libril.so中的event機制, 在RIL_startEventLoop中,是最核心的由多路I/O驅動的訊息迴圈。
2. 初始化librefrence_ril.so,也就是跟硬體或模擬硬體modem通訊的部分(後面統一稱硬體), 通過RIL_Init函式完成。
3. 通過RIL_Init獲取一組函式指標RIL_RadioFunctions, 並通過RIL_register完成註冊,並開啟接受上層命令的socket通道。
首先看第一個任務,也就是RIL_startEventLoop函式。RIL_startEventLoop在ril.cpp中實現, 它的主要目的是通過pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一個dispatch執行緒,入口點在eventLoop. 而eventLoop中,會調ril_event.cpp中的ril_event_loop()函式,建立起訊息(event)佇列機制。
我們來仔細看看這一訊息佇列的機制,這些程式碼都在ril_event.cpp中。
void ril_event_init();
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param);
void ril_event_add(struct ril_event * ev);
void ril_timer_add(struct ril_event * ev, struct timeval * tv);
void ril_event_del(struct ril_event * ev);
void ril_event_loop();
struct ril_event {
struct ril_event *next;
struct ril_event *prev;
int fd;
int index;
bool persist;
struct timeval timeout;
ril_event_cb func;
void *param;
};
每個ril_event結構,與一個fd控制代碼繫結(可以是檔案,socket,管道等),並且帶一個func指標去執行指定的操作。
具體流程是: ril_event_init完成後,通過ril_event_set來配置一新ril_event,並通過ril_event_add加入佇列之中(實 際通常用rilEventAddWakeup來新增),add會把佇列裡所有ril_event的fd,放入一個fd集合readFds中。這樣 ril_event_loop能通過一個多路複用I/O的機制(select)來等待這些fd, 如果任何一個fd有資料寫入,則進入分析流程processTimeouts(),processReadReadies(&rfds, n),firePending()。 後文會詳細分析這些流程。
另外我們可以看到, 在進入ril_event_loop之前, 已經掛入了一s_wakeupfd_event, 通過pipe的機制實現的, 這個event的目的是可以在一些情況下,能內部喚醒ril_event_loop的多路複用阻塞,比如一些帶timeout的命令timeout到期的 時候。
至此第一個任務分析完畢,這樣便建立起了基於event佇列的訊息迴圈,稍後便可以接受上層發來的的請求了(上層請求的event物件建立,在第三個任務中)。
接下來看第二個任務,這個任務的入口是RIL_Init, RIL_Init首先通過引數獲取硬體介面的裝置檔案或模擬硬體介面的socket. 接下來便新開一個執行緒繼續初始化, 即mainLoop。
mainLoop的主要任務是建立起與硬體的通訊,然後通過read方法阻塞等待硬體的主動上報或響應。在註冊一些基礎回撥 (timeout,readerclose)後,mainLoop首先開啟硬體裝置檔案,建立起與硬體的通訊,s_device_path和s_port 是前面獲取的裝置路徑引數,將其開啟(兩者可以同時開啟並擁有各自的reader,這裡也很容易新增雙卡雙待等支援)。
接下來通過 at_open函式建立起這一裝置檔案上的reader等待迴圈,這也是通過新建一個執行緒完成, ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr),入口點readerLoop。
AT命令都是以rn或nr的換行符來作為分隔符的,所以readerLoop是line驅動的,除非出錯,超時等,否則會讀到一行完整的響應或主動上 報,才會返回。這個迴圈跑起來以後,我們基本的AT響應機制已經建立了起來。它的具體分析,包括at_open中掛接的ATUnsolHandler, 我們都放到後面分析response的連載文章裡去。
有了響應的機制(當然,能與硬體通訊也已經可以發請求了),通過 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0),跑到initializeCallback中,執行一些Modem的初始化命令,主要都是AT命令的方式。發AT命令的 流程,我們放到後面分析request的連載文章裡。這裡可以看到,主要是一些引數配置,以及網路狀態的檢查等。至此第二個任務分析完畢,硬體已經可以訪 問了。
最後是第三個任務。第三個任務是由RIL_Init的返回值開始的,這是一個RIL_RadioFunctions結構的指標。
typedef struct {
int version; /* set to RIL_VERSION */
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
} RIL_RadioFunctions;
其中最重要的是onRequest域,上層來的請求都由這個函式進行對映後轉換成對應的AT命令發給硬體。
rild通過RIL_register註冊這一指標。
RIL_register中要完成的另外一個任務,就是開啟前面提到的跟上層通訊的socket介面(s_fdListen是主介面,s_fdDebug供除錯時使用)。
然後將這兩個socket介面使用任務一中實現的機制進行註冊(僅列出s_fdListen)
ril_event_set (&s_listen_event, s_fdListen, false,
listenCallback, NULL);
rilEventAddWakeup (&s_listen_event);
這樣將兩個socket加到任務一中建立起來多路複用I/O的檢查控制代碼集合中,一旦有上層來的(除錯)請求,event機制便能響應處理了。到這裡啟動流程已經分析完畢。
Android Phone分析(四)
2010-01-27 17:52
request流程
1. 多路複用I/O機制的運轉
上文說到request是接收,是通過ril_event_loop中的多路複用I/O,也對初始化做了分析.現在我們來仔細看看這個機制如何運轉.
ril_event_set負責配置一個event,主要有兩種event:
ril_event_add新增使用多路I/O的event,它負責將其掛到佇列,同時將event的通道控制代碼fd加入到watch_table,然後通過select等待.
ril_timer_add新增timer event,它將其掛在佇列,同時重新計算最短超時時間.
無論哪種add,最後都會呼叫triggerEvLoop來重新整理佇列,更新超時值或等待物件.
2010-01-27 17:51
分析初始化流程,主入口是rild.c中的main函式,主要完成三個任務:
1. 開啟libril.so中的event機制, 在RIL_startEventLoop中,是最核心的由多路I/O驅動的訊息迴圈。
2. 初始化librefrence_ril.so,也就是跟硬體或模擬硬體modem通訊的部分(後面統一稱硬體), 通過RIL_Init函式完成。
3. 通過RIL_Init獲取一組函式指標RIL_RadioFunctions, 並通過RIL_register完成註冊,並開啟接受上層命令的socket通道。
首先看第一個任務,也就是RIL_startEventLoop函式。RIL_startEventLoop在ril.cpp中實現, 它的主要目的是通過pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一個dispatch執行緒,入口點在eventLoop. 而eventLoop中,會調ril_event.cpp中的ril_event_loop()函式,建立起訊息(event)佇列機制。
我們來仔細看看這一訊息佇列的機制,這些程式碼都在ril_event.cpp中。
void ril_event_init();
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param);
void ril_event_add(struct ril_event * ev);
void ril_timer_add(struct ril_event * ev, struct timeval * tv);
void ril_event_del(struct ril_event * ev);
void ril_event_loop();
struct ril_event {
struct ril_event *next;
struct ril_event *prev;
int fd;
int index;
bool persist;
struct timeval timeout;
ril_event_cb func;
void *param;
};
每個ril_event結構,與一個fd控制代碼繫結(可以是檔案,socket,管道等),並且帶一個func指標去執行指定的操作。
具體流程是: ril_event_init完成後,通過ril_event_set來配置一新ril_event,並通過ril_event_add加入佇列之中(實 際通常用rilEventAddWakeup來新增),add會把佇列裡所有ril_event的fd,放入一個fd集合readFds中。這樣 ril_event_loop能通過一個多路複用I/O的機制(select)來等待這些fd, 如果任何一個fd有資料寫入,則進入分析流程processTimeouts(),processReadReadies(&rfds, n),firePending()。 後文會詳細分析這些流程。
另外我們可以看到, 在進入ril_event_loop之前, 已經掛入了一s_wakeupfd_event, 通過pipe的機制實現的, 這個event的目的是可以在一些情況下,能內部喚醒ril_event_loop的多路複用阻塞,比如一些帶timeout的命令timeout到期的 時候。
至此第一個任務分析完畢,這樣便建立起了基於event佇列的訊息迴圈,稍後便可以接受上層發來的的請求了(上層請求的event物件建立,在第三個任務中)。
接下來看第二個任務,這個任務的入口是RIL_Init, RIL_Init首先通過引數獲取硬體介面的裝置檔案或模擬硬體介面的socket. 接下來便新開一個執行緒繼續初始化, 即mainLoop。
mainLoop的主要任務是建立起與硬體的通訊,然後通過read方法阻塞等待硬體的主動上報或響應。在註冊一些基礎回撥 (timeout,readerclose)後,mainLoop首先開啟硬體裝置檔案,建立起與硬體的通訊,s_device_path和s_port 是前面獲取的裝置路徑引數,將其開啟(兩者可以同時開啟並擁有各自的reader,這裡也很容易新增雙卡雙待等支援)。
接下來通過 at_open函式建立起這一裝置檔案上的reader等待迴圈,這也是通過新建一個執行緒完成, ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr),入口點readerLoop。
AT命令都是以rn或nr的換行符來作為分隔符的,所以readerLoop是line驅動的,除非出錯,超時等,否則會讀到一行完整的響應或主動上 報,才會返回。這個迴圈跑起來以後,我們基本的AT響應機制已經建立了起來。它的具體分析,包括at_open中掛接的ATUnsolHandler, 我們都放到後面分析response的連載文章裡去。
有了響應的機制(當然,能與硬體通訊也已經可以發請求了),通過 RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0),跑到initializeCallback中,執行一些Modem的初始化命令,主要都是AT命令的方式。發AT命令的 流程,我們放到後面分析request的連載文章裡。這裡可以看到,主要是一些引數配置,以及網路狀態的檢查等。至此第二個任務分析完畢,硬體已經可以訪 問了。
最後是第三個任務。第三個任務是由RIL_Init的返回值開始的,這是一個RIL_RadioFunctions結構的指標。
typedef struct {
int version; /* set to RIL_VERSION */
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
} RIL_RadioFunctions;
其中最重要的是onRequest域,上層來的請求都由這個函式進行對映後轉換成對應的AT命令發給硬體。
rild通過RIL_register註冊這一指標。
RIL_register中要完成的另外一個任務,就是開啟前面提到的跟上層通訊的socket介面(s_fdListen是主介面,s_fdDebug供除錯時使用)。
然後將這兩個socket介面使用任務一中實現的機制進行註冊(僅列出s_fdListen)
ril_event_set (&s_listen_event, s_fdListen, false,
listenCallback, NULL);
rilEventAddWakeup (&s_listen_event);
這樣將兩個socket加到任務一中建立起來多路複用I/O的檢查控制代碼集合中,一旦有上層來的(除錯)請求,event機制便能響應處理了。到這裡啟動流程已經分析完畢。
Android
2010-01-27 17:52
request流程
1. 多路複用I/O機制的運轉
上文說到request是接收,是通過ril_event_loop中的多路複用I/O,也對初始化做了分析.現在我們來仔細看看這個機制如何運轉.
ril_event_set負責配置一個event,主要有兩種event:
ril_event_add新增使用多路I/O的event,它負責將其掛到佇列,同時將event的通道控制代碼fd加入到watch_table,然後通過select等待.
ril_timer_add新增timer event,它將其掛在佇列,同時重新計算最短超時時間.
無論哪種add,最後都會呼叫triggerEvLoop來重新整理佇列,更新超時值或等待物件.