RILD 启动与实现过程

1.在system/core/rootdir/init.rc中ril-daemon定义
Rild是Init进程启动的一个本地服务,采用了socket通讯这种通讯手段,是具体AT指令合成者与应答解析者
RILD管理框架,AT相关的xxxril.so动态链接库,以便适应不同的modem
RILJ <--socket通信--> RILC <--AT()--> modem
#创建一个名为"ril-daemon"的进程,这个进程要执行的程序是/system/bin/rild
service ril-daemon /system/bin/rild #源码在hardware/ril/rild/rild.c, 在Android中指定该文件编译为模块rild, 仅实现一main函数作为整个ril层的入口点,负责完成初始化
   class main #指定分组为main,同一分组的服务,可以统一启动与停止
   socket rild stream 660 root radio #创建一个unix域的名为/dev/socket/rild的套接字,并传递它的文件描述符给已启动的进程.
   socket rild-debug stream 660 radio system #创建一个unix域的名为/dev/socket/rild-debug的套接字,并传递它的文件描述符给已启动的进程.
   user root
   group radio cache inet misc audio log qcom_diag
   
2. rild,libreference-ril.so,libril.so,radiooptions的关系
rild【hardware/ril/rild/rild.c ,ril层的入口点,负责完成初始化,rild的共享库中有一个为libril】
libril【hardware/ril/libril/* ,组成部分为ril.cpp,ril_event.cpp, 主要完成同上层RILJ用socket通信,将ril请求传递给libreference-ril.so,并将其反馈回传给调用进程】
libreference-ril【hardware/ril/libreference-ril/*,libreference-ril的共享库中有一个为libril. 转换libril的请求为AT命令发送给Modem,同时监控Modem的反馈信息,并传递回libril.so】
radiooptions【hardware/ril/rild/radiooptions.c, radiooptiongs通过获取启动参数,利用socket与rild通信,可供调试时配置Modem参数】


3.rild的启动的流程【hardware/ril/rild/rild.c】
........
extern void RIL_register (const RIL_RadioFunctions *callbacks);//【见详解】
........
extern void RIL_startEventLoop();
........
int main(int argc, char **argv) // 被init守护进程调用执行
{
   ........
   //开启EventLoop循环,完成RIL与RILJ层数据交互(通过Socket)
   const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
   const RIL_RadioFunctions *funcs;
   ........
   rilLibPath = REFERENCE_RIL_PATH; // 连接库地址:/system/lib/libreference-ril.so
   ........
   switchUser(); // 切换UID为AID_RADIO
   dlHandle = dlopen(rilLibPath, RTLD_NOW); // 以RTLD_NOW(立即决定,返回前解除所有未决定的符号)模式打开libreference-ril.so的动态连接库文件,并返回一个句柄给调用进程
   ........
   RIL_startEventLoop(); // 开启libril.so共享库中的event机制,由于将上层传入的command内容转换为AT命令发送到modem并将回应发回上层,是由多路I/O驱动的消息循环【见详解】
   
   
   //打开动态库reference并构建ReaderLoop循环,完成RIL与Modem层数据交互(通过AT)
   //dlsym通过句柄和连接符名称获取函数名或者变量名,并强制转换为rilInit函数类型
   // 从连接库中寻找RIL_Init函数地址 
   rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); 
   ........
   funcs = rilInit(&s_rilEnv, argc, rilArgv); //调用rilInit函数进行初始化INIT,同时得到reference-ril的回调函数【见详解RIL_Init】
   
   RLOGD("RIL_Init rilInit completed");
   
   
   // 注册reference的回调函数
   RIL_register(funcs); // 完成注册rilInit得到的回调函数funcs,并打开接收上层RILJ命令的socket通道【见详解】
   ........
}

// hardware/ril/libril/ril.cpp 框架和处理方式由ril.cpp管理,差异化的AT命令由reference实现
........
#include <telephony/ril.h>
........
static void * eventLoop(void *param) { //等待在事件端口(串口,socket),一旦有数据到达就根据登记的event回调函数进行处理,
   int ret;
   int filedes[2];

   ril_event_init();// Event的初始化,初始化ril_event.cpp中几个重要的成员变量【见详解】
   ........
   ret = pipe(filedes);//创建匿名管道
   s_fdWakeupRead = filedes[0]; //s_fdWakeupRead为管道读端
   s_fdWakeupWrite = filedes[1]; //s_fdWakeupWrite为管道写端 
   fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK); //设置管道读端为O_NONBLOCK非阻塞 
   ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true, processWakeupCallback, NULL);//创建一个Event
   // 将上面创建的Event加入到watch_table中,这里起到唤醒LoopEvent的作用,
   rilEventAddWakeup (&s_wakeupfd_event);//向监控表watch_table添加一个s_wakeupfd_event事件,通过向管道s_fdWakeupWrite中写入来触发事件循环 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值