property_set/property_get源码解析

昨天和同事花了近半天才梳理出来一个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权限校验,这个分析和前面其他同学的总结是一致的!

本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com

请先登录后发表评论
  • 最新评论
  • 总共0条评论