zoukankan      html  css  js  c++  java
  • Linux + RIL.pdf

    android 的 ril位于应用程序框架与内核之间,分成了两个部分,一个部分是rild,它负责socket与应用程序框架进行通信。另外一个部分是Vendor RIL,这个部分负责向下通过两种方式与radio进行通信,它们是直接与radio通信的AT指令通道和用于传输包数据的通道,数据通道用于手机的上网功能。

    启动过程:http://www.cnblogs.com/jimwind/archive/2012/12/26/2833467.html

    对于RIL的java框架部分,也被分成了两个部分,一个是RIL模块,这个模块主要用于与下层的rild进行通信,另外一个是Phone模块,这个模块直接暴露电话功能接口给应用开发用户,供他们调用以进行电话功能的实现。

    [rild文件夹]

    [LOCAL_MODULE:= rild_c]

    RIL守护进程,开机是被init守护进程调用启动,里面的main函数作为入口点,负责完成RIL初始化工作。

    rild.c文件中,将完成ril的加载过程,它会执行如下操作:

    1、动态加载Vendor RIL的.so文件;--- dlHandle = dlopen("/system/lib/libreference-ril_c.so",RTLD_NOW);

    2、执行RIL_startEventLoop()开启消息队列以进行事件监听;RIL_startEventLoop();

    3、通过执行VendorRIL的rilInit()方法来进行VendorRIL与libril的关系建立。dlsym(dlHandle, "RILCore_Init");  //reference-ril/reference-core.c RILCore_Init()

    [libril文件夹]

    [LOCAL_MODULE:= libril_c]

    在编译时libril被链入rild,它为rild提供了event处理功能,还提供了在rild与VendorRIL之间传递请求和响应消息的能力。

    libril提供的主要功能分布在两个主要方法内,一个是RIL_startEventLoop()方法,另一个是RIL_register()方法。

    RIL_startEventLoop()方法所提供的功能就是启用eventLoop线程,开始执行RIL消息队列。

    RIL_register()方法的主要功能就是启动名为rild的监听端口,等待java端通过socket进行连接。

    [reference-ril文件夹]

    [LOCAL_MODULE:= libreference-ril_c]

    Android自带的VendorRIL的参考实现。被编译成.so文件,由于本部分是厂商定制的重点所在,所以被设计为松散耦合,且可灵活配置的。在rild中通过opendl()方式加载。

    libreference.so负责直接与radio通信,这包括将来自libril的指令转换为AT指令,并且将AT指令写入radio中。

    reference-ril会接收调用者传来的参数,参数内容为与radio的通信方式。如通过串口连接radio,那么参数为这个形式:-d /dev/ttySx

    Android RIL 中的消息(event)队列机制:

    在Android RIL中,为了达到等待多路输入并且不出现阻塞的目的,使用了IO多路复用机制。

    如果使用阻塞I/O进行网络的读取写入,这意味着假如需要同时从两个网络文件描述符中读内容,那么如果读取操作在等待网络数据到来,这将可能很称时间阻塞在一个描述符上,另一个网络文件描述符不管有没有数据到来都无法被读取。

    I/O多路转接技术在这里提供了另一种比较好的解决方案:

    它会先构造一张有关I/O描述符的列表,然后调用select函数,当IO描述符列表中的一个描述符准备好进行I/O时,该函数返回,并告知可以读或写哪个描述符。

    Android RIL中消息队列的核心实现思想就是这种I/O多路转接技术。

    消息队列机制的实现在ril_event.cpp中,其中被定义的ril_event结构是消息的主体

    每个ril_event结构,与一个fd句柄绑定(可以是文件,socket,管道等),并且带一个func指针,这个func指针所指的函数是个回调函数,它指定了当所绑定的fd准备好进行读取时所要进行的操作。

    消息队列的开始点为RIL_startEventLoop函数,RIL_startEventLoop在ril.cpp中实现,它的主要目的是通过pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一个dispatch线程,线程入口点在eventLoop。而在eventLoop中,会调ril_event.cpp中的ril_event_loop()函数,建立起消息队列机制

    ril_event是一个带有链表行为的struct,它最主要的成员一个是fd,一个是func

    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的操作是通过ril_event_set()来完成的,并通过ril_event_add()加入到消息队列中,add会把队列里所有ril_event的fd,放入一个fd集合readFds。这样ril_event_loop能通过一个多路复用I/O的机制(select)来等待这些fd。

    在进入ril_event_loop()之前,在eventLoop中已经创建和挂入了s_wakeupfd_event,它是通过pipe的机制实现的,这个管道fd的回调函数并没有实现什么功能,它的目的只是为了让select方法能返回一次,这样select()方法就能重新跟踪新加入事件队列的fd和timeout设置。

    所以在添加新fd到eventLoop时,往往不是直接调用ril_event_add,实际通常用rilEventAddWakeup来添加,这个方法除了会间接调用ril_event_add外,还会调用triggerEvLoop()函数来向s_fdWakeupWrite中写入一个空字符,这样select()函数会返回并重新执行,新加入的文件描述符便得以被select()加载并跟踪。

    如果在ril_event队列中任何一个fd已经准备好,则进入分析流程:

    processTimeouts(),processReadReadies(&rfds, n),firePending()

    其中firePending()方法执行这个event的func,也就是回调函数。

    在Android RIL初始化完成后,将有几个event被挂入到eventLoop中:

    1.s_listen_event: 名为rild的socket,主要request & response通道。

    2.s_debug_event:名为rild-debug的socket,调试用request & response通道。

    3.s_wakeupfd_event: 无名管道,用于队列主动唤醒

    这其中最为重要的event就是s_listen_event,它作为request与response的通道实现

    在ril_event.cpp中还持有一个watch_table数组,一个timer_list链表和一个pending_list链表。

    watch_table数组的目的目的很单纯,存放当前被eventLoop等待的ril_event(非timer event),供eventLoop唤醒时使用。

    timer_list是存放timer event的链表,在eventLoop唤醒时要对这些timer event单独进行处理

    pending_list:待处理(对其回调函数进行调用)的所有ril_event的链表

    Android RIL编译结构

    rild: 被编译成可执行文件,rild以守护进程的形式执行

    libril:将被编译为共享库,并被链入rild

    d

      

  • 相关阅读:
    Android-View动画
    Android-RemoteView-桌面小部件
    系统的Drawable(四)-LayerListDrawable
    Android-Drawable(三)
    系统的Drawable(二)-Selector
    系统的Drawable(一)
    Android View事件分发-从源码分析
    打游戏要存进度-备忘录模式
    Java 内部类.md
    docker 常用 命令
  • 原文地址:https://www.cnblogs.com/jimwind/p/2832976.html
Copyright © 2011-2022 走看看