ril/rild/rild.c->main()为函数入口
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.消息队列select为非阻塞的去轮询事件
2.read的阻塞的去读取上层发下来的命令,并响应
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int main(int argc, char **argv)
{
const char * rilLibPath = NULL;
char **rilArgv;
void *dlHandle;
const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
const RIL_RadioFunctions *funcs;
char libPath[PROPERTY_VALUE_MAX];
unsigned char hasLibArgs = 0;
........
OpenLib:
#endif
switchUser();
/*打开dlopen()函数,就会动态去加载动态库vendor RIL 获取由RIL_register(funcs);注册进来的参数,并解析*/
dlHandle = dlopen(rilLibPath, RTLD_NOW);
if (dlHandle == NULL) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit(-1);
}
/*消息队列的入口,添加到select,用阻塞方式去读取那些ril_event_set()的数据##每当看到打印信息,不按顺序打下来说明阻塞##*/
RIL_startEventLoop();
/*通过dlsym函数得到rilInit函数指针的引用*/
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
if (rilInit == NULL) {
fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);
exit(-1);
}
if (hasLibArgs) {
rilArgv = argv + i - 1;
argc = argc -i + 1;
} else {
static char * newArgv[MAX_LIB_ARGS];
static char args[PROPERTY_VALUE_MAX];
rilArgv = newArgv;
property_get(LIB_ARGS_PROPERTY, args, "");
argc = make_argv(args, rilArgv);
}
// Make sure there's a reasonable argv[0]
rilArgv[0] = argv[0];
/*利用得到的rilInit函数指针,调用真正的RIL_Init ,实际是动态加载动态库去链接reference-ril.c ,由dlopen()函数加载*/
funcs = rilInit(&s_rilEnv, argc, rilArgv);
/*RIL_register作用一:把vendor RIL(即RIL_init) 注册到reference-ril库去等待,dopen()函数加载链接
附:RIL_init通过是onRequest()方法,将上层来的请求进行映射后转换成对应的AT命令发给硬件,rild通过RIL_register注册这一指针。
RIL_register作用二:创建rild socket主要是等待java层得数据通过,传到下一层,还创建debug socket*/
RIL_register(funcs);
done:
while(1) {
// sleep(UINT32_MAX) seems to return immediately on bionic
sleep(0x00ffffff);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
所有文件:
hardware/ril/libril$ ls
Android.mk NOTICE ril_event.h ril.cpp ril_event.cpp ril_commands.h ril_unsol_commands.h
MODULE_LICENSE_APACHE2
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
与rild结合相当紧密,是其共享库,编译时就已经建立了这一关系。组成部分为ril.cpp,ril_event.cpp。libril.so驻留在rild这一守护进程中,主要完成同上层通信的工作,接受ril请求并传递给librefrence_ril.so, 同时把来自librefrence_ril.so的反馈回传给调用进程
在编译时libril被链入rild,它为rild提供了event处理功能,还提供了在rild与Vendor RIL之间传递请求和响应消息的能力。
Libril提供的主要功能分布在两个主要方法内,一个是RIL_startEventLoop()方法,另一个是RIL_register()方法
RIL_startEventLoop()方法所提供的功能就是启用eventLoop线程,开始执行RIL消息队列。
RIL_register()方法的主要功能是启动名为rild 的监听端口,等待java 端通过socket进行连接。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
RIL_startEventLoop函数 libril/ril.cpp->RIL_startEventLoop()
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern "C" void
RIL_startEventLoop(void) {
int ret;
pthread_attr_t attr;
LOGD("-2--ril.cpp--RIL_startEventLoop---");
/* 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);
LOGD("-1-ril.cpp--kai-kou--pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);------");
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);//创建线程,为入口函数
LOGD("-2.....-ril.cpp--tiao-chu--rpthread_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;
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
开启libril.so中的event机制, 在RIL_startEventLoop中,是最核心的由多路I/O驱动的消息循环
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对象建立,在第三个任务中)。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void *
eventLoop(void *param) {
int ret;
int filedes[2];
LOGD("--2.--ril.cpp----eventLoop-zhi--xing--");
LOGD("-2.1-RIL.C-ril_event_init--kai-shi -");
ril_event_init();//初始化
LOGD("-2.3-RIL.C-ril_event_init--tiao-chu -");
pthread_mutex_lock(&s_startupMutex);
s_started = 1;
pthread_cond_broadcast(&s_startupCond);
pthread_mutex_unlock(&s_startupMutex);
ret = pipe(filedes);
if (ret < 0) {
LOGE("Error in pipe() errno:%d", errno);
return NULL;
}
s_fdWakeupRead = filedes[0];// 消息循环中侦听
s_fdWakeupWrite = filedes[1];// 用于通知消息循环定义消息已发送
LOGD("--2.4-ril.cpp--evnetloop---- ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
processWakeupCallback, NULL);--");
fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);
/*先执行 processWakeupCallback中的read函数,再把参数,传给ril_event_set进行设置*/
ril_event_set(&s_wakeupfd_event, s_fdWakeupRead, true, processWakeupCallback, NULL);
/*在ilEventAddWakeup进行ril_evnet_add事件添加和triggerEvLoop()实现管道写端*/
LOGD("-2.6--ril.cpp--eventloop- rilEventAddWakeup (&s_wakeupfd_event);---");
rilEventAddWakeup (&s_wakeupfd_event);
LOGD("----tiao-chu --ril_event_set--add");
// Only returns on error
LOGD("--100-ril.cpp-cong --eventloop---tiao_ru--ril_event_loop()----");
ril_event_loop();
LOGD("-102-ril.cpp-cong--eventloop--tiaochu---ril_event_loop()----");
LOGE ("error in event_loop_base errno:%d", errno);
return NULL;
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ril_event_init()主要工作是清零和处理三种函数(定时,监听,挂起);
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Initialize internal data structs
void ril_event_init()
{
MUTEX_INIT();
LOGD("-2.2-Ril_evnet.cpp-ril_event_init-shi-xian-han-shu-");
FD_ZERO(&readFds);
init_list(&timer_list);
init_list(&pending_list);
memset(watch_table, 0, sizeof(watch_table));
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ril_event_set()的作用是:通过管道,对读到的数据进行初始化 ---------注册进程唤醒事件回调
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
{
LOGD("----RIL_evnent.cpp-shi-xian--void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)-");
dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev);
memset(ev, 0, sizeof(struct ril_event));
ev->fd = fd;
ev->index = -1;
ev->persist = persist;
ev->func = func;
ev->param = param;
fcntl(fd, F_SETFL, O_NONBLOCK);
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
用read()得方法去唤醒fd,把可执行得弹出来,ril_event 去复位定时器,把缓冲区清空
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/**
* A write on the wakeup fd is done just to pop us out of select()
* We empty the buffer here and then ril_event will reset the timers on the
* way back down
*/
static void processWakeupCallback(int fd, short flags, void *param) {
char buff[16];
int ret;
LOGD("--2.5-ril_event_set--processWakeupCallback- read(s_fdWakeupRead, &buff, sizeof(buff));---");
LOGV("processWakeupCallback");
/* empty our wakeup socket out */
do {
ret = read(s_fdWakeupRead, &buff, sizeof(buff));
} while (ret > 0 || (ret < 0 && errno == EINTR));
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
rilEventAddWakeup的作用是:作为ril_event_add(ev);和triggerEvLoop();入口函数,真正的把数据数组 watch_table[i] = ev上去,等待selcet轮询,最后写入
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void rilEventAddWakeup(struct ril_event *ev) {
ril_event_add(ev);
triggerEvLoop();
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Add event to watch list
void ril_event_add(struct ril_event * ev)
{
LOGD("---RIL_evnent.cpp--shi--xian--void ril_event_add(struct ril_event * ev)----");
dlog("~~~~ +ril_event_add ~~~~");
MUTEX_ACQUIRE();
for (int i = 0; i < MAX_FD_EVLL) {
//1:
watch_table[i] = ev;//把上面ril_event_add函数添加的事件_wakeupfd_event结构体添加到这个数组来
ev->index = i;
dlog("~~~~ added at %d ~~~~", i);
dump_event(ev);
//2:
FD_SET(ev->fd, &readFds);//把上面数组,放到readFds来
if (ev->fd >= nfds) nfds = ev->fd+1;
dlog("~~~~ nfds = %d ~~~~", nfds);
break;ENTS; i++) {
if (watch_table[i] == NU
}
}
MUTEX_RELEASE();
dlog("~~~~ -ril_event_add ~~~~");
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
就是上面管道读完,收到数据后,再通过写端,写到对应的数组去(readFs)
static void triggerEvLoop() {
int ret;
LOGD("--- ret = write (s_fdWakeupWrite, " ", 1);---");
if (!pthread_equal(pthread_self(), s_tid_dispatch)) {
/* trigger event loop to wakeup. No reason to do this,
* if we're in the event loop thread */
do {
ret = write (s_fdWakeupWrite, " ", 1);
} while (ret < 0 && errno == EINTR);
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
上面工作一做完,说明通过pipe机制已经把数据读到,并放入数组,而数组且放在readFs队列中,等待ril_event_loop()函数t轮询
下面为ril_event_loop()开始轮询的整个过程:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void ril_event_loop()
{
int n;
fd_set rfds;
struct timeval tv;
struct timeval * ptv;
LOGD("-101--ril_event.cpp--shi_xian--ril_event_loop-limain----");
for (;;) {//死循环的轮询
// make local copy of read fd_set
LOGD("-101.1--kaishi--ril_event_loop-memcpy(&rfds, &readFds, sizeof(fd_set));---");
memcpy(&rfds, &readFds, sizeof(fd_set));把上面通过管道机制读到得数据,换个名字,放到rfds去
if (-1 == calcNextTimeout(&tv)) {// 获取超时参数,若失败则返回-1。
// no pending timers; block indefinitely
dlog("~~~~ no timers; blocking indefinitely ~~~~");
ptv = NULL;
} else {// 获取成功,则使用该值。
dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);
ptv = &tv;
}
printReadies(&rfds);
LOGD("-101.2--ril_event.cpp---ril_event_loop---tiao-ru--select ------");
LOGI("--------select ready");
//初始化到这里结束。
n = select(nfds, &rfds, NULL, NULL, ptv);//等待fd唤醒,通过selcet多路I/o复用机制去唤醒管道来的数据
LOGD("---101.3--ril_event.cpp---ril_event_loop--tiao -chu--select---");
LOGI("-----------select go");
printReadies(&rfds);
dlog("~~~~ %d events fired ~~~~", n);
if (n < 0) {
if (errno == EINTR) continue;
LOGE("ril_event: select error (%d)", errno);
// bail?
return;
}
LOGD("--------101.4.1-------ril_event_loop--chu-li-- processTimeouts();--");
// Check for timeouts
processTimeouts();// 处理定时消息 ,处理ril_event_init ->pending_list
// Check for read-ready
LOGD("-----101.4.2-----ril_event_loop--chu-li-- processReadReadies(&rfds, n)--");
processReadReadies(&rfds, n); // 处理侦听消息 ,处理ril_event_init ->watch_list
// Fire away
LOGD("-----1041.4.3-----ril_event_loop--chu-li-- firePending()---ril_event_loop()--OVER1--");
firePending(); // 处理挂起消息
LOGD("-----1041.4.3-----ril_event_loop--chu-li-- firePending()---ril_event_loop()--OVER2--");
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void processTimeouts()
{
LOGD("---1-DSJT--processTimeouts--");
LOGI("-------processTimeouts");
dlog("~~~~ +processTimeouts ~~~~");
MUTEX_ACQUIRE();
struct timeval now;
struct ril_event * tev = timer_list.next;
struct ril_event * next;
getNow(&now);//获取当前时间
// walk list, see if now >= ev->timeout for any events
dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);
while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) {// 查找所有当前时间点以前的消息
// Timer expired
dlog("~~~~ firing timer ~~~~");
next = tev->next;
removeFromList(tev);//从定时消息队列中移除,就是已经做完的内容
addToList(tev, &pending_list); // 添加至挂起列表(pending_list)中
tev = next;
}
MUTEX_RELEASE();
dlog("~~~~ -processTimeouts ~~~~");
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void addToList(struct ril_event * ev, struct ril_event * list)
{
LOGD("-----TJLB--addToList---");
ev->next = list;
ev->prev = list->prev;
ev->prev->next = ev;
list->prev = ev;
dump_event(ev);
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void processReadReadies(fd_set * rfds, int n)
{
LOGD("--2--JT---procssReadReadies--");
LOGI("-------processReadReadies");
dlog("~~~~ +processReadReadies (%d) ~~~~", n);
MUTEX_ACQUIRE();
for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) { // 此处判断描述符是否在当前循环的等待列表中。
struct ril_event * rev = watch_table[i];
if (rev != NULL && FD_ISSET(rev->fd, rfds)) {
addToList(rev, &pending_list);// 添加至挂起列表(pending_list)中
if (rev->persist == false) { // 会判断ril_event的persist参数,以决定是否从watch_list移除该消息。
removeWatch(rev, i);
}
n--;
}
}
MUTEX_RELEASE();
dlog("~~~~ -processReadReadies (%d) ~~~~", n);
}