多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
Rild的代码在Rild.c中,它是一个应用程序。从它的main开始分析,代码如下所示: **Rild.c** ~~~ int main(int argc, char **argv) { //动态库的位置由rilLibPath决定 constchar * rilLibPath = NULL; char**rilArgv; void*dlHandle; /* Rild规定动态库必须实现一个叫Ril_init函数,这个函数的第一个参数指向结构体 RIL_Env,而它的返回值指向结构体RIL_ RadioFunctions。这两个结构体就是在 图9-7中提到的接口。这两个接口的具体内容,后文再做分析。 */ constRIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **); constRIL_RadioFunctions *funcs; charlibPath[PROPERTY_VALUE_MAX]; unsigned char hasLibArgs = 0; int i; //Rild由init启动,没有对应的启动参数,所以这个for循环不会进来。 for (i= 1; i < argc ;) { if(0 == strcmp(argv[i], "-l") && (argc - i > 1)) { rilLibPath = argv[i + 1]; i += 2; }else if (0 == strcmp(argv[i], "--")) { i++; hasLibArgs = 1; break; }else { usage(argv[0]); } } if(rilLibPath == NULL) { /* 读取系统属性,LIB_PATH_PROPERTY的值为"rild.libpath“,模拟器上 和RIL相关的属性值有两个,分别是: rild.libpath=/system/lib/libreference-ril.so rild.libargs=-d /dev/ttyS0 上面这些值都定义在build/target/board/generic/system.prop文件中 不同厂商可以有自己对应的实现。 */ if( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) { goto done; }else { /* 这里,使用参考的动态库进行分析,它的位置为 /system/lib/libreference-ril.so。 */ rilLibPath = libPath; } } ...... //和模拟器相关的一些内容 switchUser();//设置Rild的组用户为radio //通过dlopen系统加载动态库 dlHandle = dlopen(rilLibPath, RTLD_NOW); ...... //① 启动EventLoop,事件处理 RIL_startEventLoop(); //得到RefRil库中RIL_Init函数的地址 rilInit= (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); ...... rilArgv[0]= argv[0]; //②调用RefRil库输出的RIL_Init函数,注意传入的第一个参数和它的返回值。 funcs= rilInit(&s_rilEnv, argc, rilArgv); //③注册上面rilInit函数的返回值(一个RIL_RadioFunctions类型的结构体)到Rild中。 RIL_register(funcs); done: while(1) { //主线程sleep,具体工作交给工作线程完成。 sleep(0x00ffffff); } } ~~~ 将上面的代码和分析结合起来,就知道了Rild解决问题的方法,代码中列出了三个关键点。我们将逐一对其进行分析。