打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
eventloop(ril.cpp)函数中定义的管道的作用(Android)

在(android源码目录)/hardware/ril/libril/ril.cpp文件中定义了一个管道:

  1. /*此段代码在ril.cpp中*/  
  2. static void *eventLoop(void *param)  
  3. {  
  4.     ret = pipe(filedes);  
  5.     …其他代码…  
  6.     s_fdWakeupRead = filedes[0];  
  7.     s_fdWakeupWrite = filedes[1];  
  8.     /*将读管道设为非阻塞方式*/  
  9.     fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK);  
  10.     /*设置s_wakeupfd_event事件的处理函数为processWakeupCallback*/  
  11.     ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,  
  12.                 processWakeupCallback, NULL);/*processWakeupCallback函数的作用是清空管道*/  
  13.     /*调用rilEventAddWakeup函数,该函数内容下文已附*/  
  14.     rilEventAddWakeup (&s_wakeupfd_event);  
  15.     // Only returns on error  
  16. ril_event_loop();  
  17. …其他代码…  
  18. }  
  19.   
  20. static void rilEventAddWakeup(struct ril_event *ev)/*此段代码在ril.cpp中*/  
  21. {  
  22.     ril_event_add(ev);/*把ev添加到监视列表watch_table数组,并将ev->fd加入readFds描述符集*/  
  23.     triggerEvLoop();/*如果此时不在evenloop线程中了,就把evenloop唤醒,该函数内容下文已附*/  
  24. }  
  25.   
  26. static void triggerEvLoop()/*此段代码在ril.cpp中*/  
  27. {  
  28.     int ret;  
  29.     if (!pthread_equal(pthread_self(), s_tid_dispatch)) {  
  30.         /* trigger event loop to wakeup. No reason to do this, 
  31.          * if we're in the event loop thread */  
  32.          do {  
  33.             ret = write (s_fdWakeupWrite, " ", 1);  
  34.          } while (ret < 0 && errno == EINTR);  
  35.     }  
  36. }  

可以从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

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android RIL结构分析与移植
浅析Android的RILD服务进程的消息循环
Android GSM驱动模块详细分析
android phone 模块分析
三、I/O模型
Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服