<二>---RIL层代码分析---RIL_startEventLoop()->eventLoop()->ril_event_loop()

 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处理功能,还提供了在rildVendor 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);
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void firePending()
{
LOGD("-------firePending");
LOGI("-------firePending");
    dlog("~~~~ +firePending ~~~~");
    struct ril_event * ev = pending_list.next;
    while (ev != &pending_list) {
        struct ril_event * next = ev->next;
        removeFromList(ev);
        ev->func(ev->fd, 0, ev->param);
        ev = next;
    }
    dlog("~~~~ -firePending ~~~~");
}

你可能感兴趣的:(timer,socket,list,struct,null,代码分析)