RIL 机制---rild守护进程
来源:互联网 发布:查看手机端口 编辑:程序博客网 时间:2024/06/11 15:00
3 守护进程
ril与上层的RILJ沟通方式是通过Socket传输数据与命令,而reference-ril与底层Modem的信号传输是通过串口用AT命令来实现。
RILC是一个守护进程,由init进程启动,init.rc文件配置如下,
service ril-daemon /system/bin/rild class main socket rild stream 660 root radio socket rild-debug stream 660 radio system user root group radio cache inet misc audio log qcom_diag
由配置文件可知,
1,如果该守护进程异常退出,android系统会进行重新加载。
2,会建立2个socket,端口号为rild负责和RILJ进行通信。
该守护进程的入口为rild.c的main方法,main方法比较长,主要逻辑如下,
1、开启EventLoop循环,完成RILC与RILJ层数据交互(通过Socket)
2、打开动态库reference并构建ReaderLoop循环,完成RIL与Modem层数据交互(通过AT)
3、注册reference的回调函数。
根据通信方法,将该守护进程分为2部分:
1,Event:利用socket完成RILC与RILJ层数据交互。
2, reference-ril:利用AT指令完成RILC与Modem层数据交互。
3.1,EventLoop
ril.cpp的RIL_startEventLoop方法如下,
extern "C" void RIL_startEventLoop(void) { /* spin up eventLoop thread and wait for it to get started */ s_started = 0; pthread_mutex_lock(&s_startupMutex); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //打开Event线程,并调用eventLoop进入循环 int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL); if (result != 0) { RLOGE("Failed to create dispatch thread: %s", strerror(result)); goto done; } while (s_started == 0) { pthread_cond_wait(&s_startupCond, &s_startupMutex); }done: pthread_mutex_unlock(&s_startupMutex);}
这样,Event线程就会监听RILJ发过来的数据了,eventLoop方法在后面会详细分析。好了,RILJ到RILC这条路已经通了。
3.2 ReaderLoop
rild.c中main方法有关加载动态库reference代码如下,
#define REFERENCE_RIL_PATH "libreference-ril.so"rilLibPath = REFERENCE_RIL_PATH;rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **)) dlsym(dlHandle, "RIL_Init");dlHandle = dlopen(rilLibPath, RTLD_NOW);//加载库•••funcs = rilInit(&s_rilEnv, argc, rilArgv);//初始化 实际调用的是RIL_Init方法
s_rilEnv结构体定义如下,也就是reference-ril可以回调ril的方法
static struct RIL_Env s_rilEnv = { RIL_onRequestComplete, RIL_onUnsolicitedResponse, RIL_requestTimedCallback};
将ril的s_rilEnv传给reference-ril的s_rilenv之后,reference-ril就可以利用该结构调用ril的方法。这样,reference-ril到ril这条路也通了。
reference-ril.c的RIL_Init主要代码如下,
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);//创建线程,入口方法是mainLoop return &s_callbacks;
在此必须要说的是, reference-ril.c还有一个main方法,其实main方法和RIL_Init方法作用几乎完全一样。
只是reference-ril.c作为动态库是调用的是RIL_Init方法,如果作为单独进程就会调用main方法。
这样,mainLoop线程就会监听Modem发过来的数据了, mainLoop方法在后面会详细分析。好了, Modem到RILC这条路已经通了。
3.3 RIL_register
rild.c中main方法有关加载动态库RIL注册的代码如下,
funcs = rilInit(&s_rilEnv, argc, rilArgv);RIL_register(funcs); //注册reference 的回调函数
当我们调用reference的初始化函数(也就是RIL_Init)后, 将会得到一个RIL_RadioFunctions类型的返回值,reference-ril.c中如下,
static const RIL_RadioFunctions s_callbacks = { RIL_VERSION, onRequest, currentState, onSupports, onCancel, getVersion};
ril.h中定义这个变量类型如下,也就是ril可以调用reference-ril的方法。
typedef struct { int version; //当前链接库的版本信息 RIL_RequestFunc onRequest; //用于Event侧向动态库发起请求 RIL_RadioStateRequest onStateRequest; //得到当前库的状态 RIL_Supports supports; //查询是否支持某个命令 RIL_Cancel onCancel; //取消一个Event的处理 RIL_GetVersion getVersion; //得到版本号 } RIL_RadioFunctions;
RIL_register 主要代码如下,
//把返回值传给s_callbacks(全局变量)memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions)); //打开RILC与RILJ之间的Socket通道 s_ril_param_socket = { RIL_SOCKET_1, /* socket_id */ -1, /* fdListen */ -1, /* fdCommand */ PHONE_PROCESS, /* processName */ &s_commands_event, /* commands_event */ &s_listen_event, /* listen_event */ processCommandsCallback, /* processCommandsCallback */ NULL /* p_rs */ };startListen(RIL_SOCKET_1, &s_ril_param_socket);// 监听rild socket
将reference-ril的callbacks传给ril的s_callbacks之后, ril就可以利用该结构调用reference-ril的方法。这样, ril到reference-ril这条路也通了。
startListen主要方法如下,
memset(socket_name, 0, sizeof(char)*10);fdListen = android_get_control_socket(socket_name); 打开RILC与RILJ之间的Socket通道 ret = listen(fdListen, 4);socket_listen_p->fdListen = fdListen; //用这个Socket通道句柄创建一个Eventril_event_set (socket_listen_p->listen_event, fdListen, false, listenCallback, socket_listen_p); rilEventAddWakeup (socket_listen_p->listen_event); //添加到Eventloop中
ril_event_set方法如下,
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);}
在第五章中,消息从socket读取之后,会回调func方法,这里的func就指向listenCallback。
3.4 消息流程
有前面的分析可知,消息会在4个模块中走一遍,消息流动方法如下,
1,从RIL到RIL。
2,从RIL到reference-ril
3, 从reference-ril到Modem
4,Modem处理完成之后,又从modem到reference-ril
5,从reference-ril到RIL
6,从RIL到RILJ。
但是,很多时候,比如来电了,这个信息是直接从Modem出发的, 只需要经过以下三个流程。
1,modem到reference-ril
2,从reference-ril到RIL
3,从RIL到RILJ。
为了便于论述,将modem主动往上层发送的消息称为上报消息;从RILJ发送出Modem处理完成之后再往上层发送的消息称为回应消息。
RILJ和ril利用socket进行通信。
ril和reference-ril在同一个进程,因此只需用简单的回调就可以完成通信。
reference-ril和Modem利用串口进行通信,每个厂商一般都不相同,但是一般都是利用tty端口进行通信。
这样,按照发送到接收,从Java层到C/C++层的顺序来仔细的捋一捋整个ril机制。
- RIL 机制---rild守护进程
- Ril分析一 rild进程
- rild进程
- Android Binder机制(三) ServiceManager守护进程
- Android Binder机制(三) ServiceManager守护进程
- android netd守护进程机制 --- netd分析
- Android RIL源码梳理(1) ——rild启动流程
- Android RIL源码梳理(1) ——rild启动流程 .
- RIL 机制源码分析
- RIL 机制---开篇
- RIL 机制---总结
- RIL 机制---消息从RILJ到RIL
- RIL 机制---消息从RIL到RILJ
- 守护进程守护自身
- 守护线程、守护进程
- RIL 机制---消息从RIL到reference-ril
- RIL 机制---消息从reference-ril到RIL
- 守护进程
- 每天学一点Swift----运算符与表达式(一)
- javascript之事件委托(事件代理)
- 获取App通知权限是否开启的方法
- Dbutils Sqlserver Update 占位符问题
- 数组去重的几种方法-基础篇
- RIL 机制---rild守护进程
- Kali 2016.2 安装 OpenVAS 9 步骤
- POJ1579简单dp
- MySQL 学习<二> 数据库的基本操作
- string和cstring互转
- Hello world!!
- linux利用文件句柄恢复oracle数据
- POJ 2240 Arbitrage 最短路 Floyd
- Vijos P2010 回文日期【回文+日期计算】