昨天和同事花了近半天才梳理出来一个rc文件中set_prop的流程,足见android底层服务设计之复杂!
init 的三个阶段,每个阶段对应的selinux域类型不一样:
域类型:kernel -> init -> init_vendor
kernel init init_vendor
init second_stage subcontext
init.selinux_setup
Init进程启动后,主要分为三个阶段内容:
第一个阶段完成以下内容:
挂载文件系统并创建目录
初始化日志输出、挂载分区设备
启用SELinux安全策略
开始第二阶段前的准备
第二个阶段完成以下内容:
初始化属性系统
执行SELinux第二阶段并恢复一些文件安全上下文
新建epoll并初始化子进程终止信号处理函数
设置其他系统属性并开启属性服务
第三阶段
通过init.rc机制,读取配置文件,来启动不同的进程
propertyservice服务
在init second_stage阶段,会启动一个propertyservice的本地socket服务,路径是"/dev/socket/" PROP_SERVICE_NAME
int SecondStageMain(int argc, char** argv) {
//....
StartPropertyService(&epoll);
}
本地socket服务主要用于系统内部间的IPC,可以参考:https://www.cnblogs.com/x_wukong/p/9554010.html
问题1、创建的propertyservice服务用来做什么?
初看,是作为property_set/get接口的服务端?其实错了;
问题2、在这个服务启动之前的property_set设置到哪里去了?
全局搜索property_set的实现,发现最终的实现是下面的代码,并没有给上面创建的propertyservice发送消息的过程,也就是其实还是在一个内存的map中保存的键值对;--------这里可能不对,set操作最终还是到init的socket处理了!
property_set方法由libcutils实现,路径在core/libcutils/ 依赖core/base/
#include <sys/_system_properties.h> int property_set(const char *key, const char *value) { return __system_property_set(key, value); } int property_get(const char *key, char *value, const char *default_value) { int len = __system_property_get(key, value); if (len > 0) { return len; } if (default_value) { len = strnlen(default_value, PROPERTY_VALUE_MAX - 1); memcpy(value, default_value, len); value[len] = '\0'; } return len; }
//见core/properties.cpp
#if !defined(__BIONIC__) static std::map<std::string, std::string>& g_properties = *new std::map<std::string, std::string>; static int __system_property_set(const char* key, const char* value) { g_properties[key] = value; return 0; } #endif
回到问题1:创建的propertyservice服务用来做什么?
send_prop走的socket,get_prop直接读的是内存中缓存的数据。
网友提出:https://blog.csdn.net/zhulove86/article/details/14681175
这样设计的优点:在android的应用运行和操作中,属性的获取的使用频率会远远大于属性修改的使用频率,既然大量的使用属性获取的操作,那么就需要考虑在操作中的效率问题。
为了提高get动作的执行效率,那么可以直接已只读的方式访问共享内存中保存的数据信息。而set动作的由于执行的频率较低,所以通过socket的方式进行操作。但是为了防止在get的时候,propertyservice中其他进程修改正在获取的属性,造成读写冲突,因此在get的时候增加了一个wait的动作。
参考:https://blog.csdn.net/Harrison509/article/details/108659469
-----------------------更新20211112---------------------------
property的get操作是通过libc库封装的方法直接读property文件的,所以这些property的selinux配置只能是给谁用配置谁的,因为文件操作最后是到内核的selinux钩子上,做selinux权限校验,这个分析和前面其他同学的总结是一致的!
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com