在(android源码目录)/hardware/ril/libril/ril.cpp文件中定义了一个管道: [cpp] view plaincopy
可以从ril_event_add和triggerEvLoop函数看出,每次调用rilEventAddWakeup时,就把安装了processWakeupCallback(作用是清空管道)处理函数的s_wakeupfd_event事件写入监视列表watch_table[]数组,然后再向管道内写入一个字节的空格。 管道的作用是这样的,eventloop函数所在的进程向下调用ril_event_loop()函数(ril_event.cpp),后者将readFds做了一个本地备份(自然s_wakeupfd_event的描述符也在里面,因为ril_event_add已将将ev->fd加入readFds描述符集)。然后再向下遇到了一个select n = select(nfds, &rfds, NULL, NULL, ptv); 此时如果管道里面有数据,s_fdWakeupRead即为可用,则select不会阻塞。因此,如果eventloop进程在这里因为没有可用的读描述符而被阻塞的话,执行rilEventAddWakeup后,管道内被写入了至少一个空格,则rfds中至少将有一个描述符变得可用,select函数返回。因此eventloop线程(此时该进程正在执行ril_event_loop函数)被select的阻塞的情况(如果被阻塞的话)将被解除。 eventloop线程继续向下执行,被写入监视列表watch_table数组的s_wakeupfd_event事件在ril_event_loop函数(ril_event.cpp)调用函数processReadReadies(&rfds, n)时放入了pending_list中,并随着firePending()函数的执行,processWakeupCallback函数(作用是清空管道)也得到执行。这样,管道的读描述符重新变得不可用,使其不影响正常的select功能。相当于将唤醒eventloop进程的“扳机”重新归位,等待下一次某个进程需要时再次调用的triggerEvLoop。 总的来说,就是通过管道内的数据有无,控制select是否解除阻塞的过程。
转载:http://hi.baidu.com/mcu99/blog/item/1b408b2c530282e48b13991e.html |
|
来自: android之情殇 > 《android》