android系统之属性系统详解Word文档格式.docx
- 文档编号:21023359
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:43
- 大小:1.66MB
android系统之属性系统详解Word文档格式.docx
《android系统之属性系统详解Word文档格式.docx》由会员分享,可在线阅读,更多相关《android系统之属性系统详解Word文档格式.docx(43页珍藏版)》请在冰豆网上搜索。
setter试图增加或者更新一个属性时,它将该属性通过unixdomainsocket发送至
propertyservice服务进程。
注意:
后两者实际并不是一个特定的进程,是加载属性的get和set操作库的客户端进程统称。
下面以海思3798MV100平台(android4.4.2)为例来分析属性系统。
2property数据的编译
属性文件的生成依赖于build/core/Makefile文件,该文件实际上主导所有文件的编译,我们这里主要看其中的属性文件的编译引导。
2.1/default.prop
这是根目录下的属性文件,该属性文件的主要内容是adb控制相关的属性:
编译后该文件的输出:
1)\out\target\product\i3798MV100\root\default.prop
build/core/Makefile中对default.prop的编译引导如下:
TARGET_ROOT_OUT就是\out\target\product\i3798MV100\root\,对应设备文件系统的根目录。
可见该属性文件的内容来自于build/tools/post_process_props.py,该py文件根据环境的设定,来设置相关的adb控制属性。
2)\out\target\product\i3798MV100\recovery\root\default.prop
recovery系统是boot启动后的另外一个程序分支,所以这里面也需要一个属性文件,
build/core/Makefile中对default.prop拷贝了一份到recovery\root\下,TARGET_RECOVERY_ROOT_OUT就是\out\target\product\i3798MV100\recovery\root\
2.2/system/build.prop
这是system分区下的属性文件,该文件收集的属性信息较多,也是打交道最多的属性文件。
主要内容是常用的版本信息,平台信息,其他设备控制信息等:
编译后该文件放在\out\target\product\i3798MV100\system\build.prop,
TARGET_OUT就是\out\target\product\i3798MV100\system\,也就是system分区在设备文件系统下的对应目录。
build/core/Makefile中对build.prop的编译引导如下:
在build.prop的编译中,定义了BUILD_FINGERPRINT,BUILD_DISPLAY_ID等变量,都在build/tools/buildinfo.sh中被引用。
由上面的mk文件片段也可以看出build.prop的生成依赖于
1)引入BUILDINFO_SH的内容
数据来源:
build/tools/buildinfo.sh
BUILDINFO_SH在本文件定义,为BUILDINFO_SH:
=build/tools/buildinfo.sh。
最后通过bash$(BUILDINFO_SH)>
$@解析得到buildinfo.sh中的全部属性。
2)引入INTERNAL_BUILD_ID_MAKEFILE的内容
/build/core/build_id.mk
INTERNAL_BUILD_ID_MAKEFILE在./build/core/version_defaults.mk中定义:
BUILD_SYSTEM在/build/core/main.mk中定义
所以INTERNAL_BUILD_ID_MAKEFILE就是/build/core/build_id.mk。
这里的作用仅仅是引入build_id.mk中定义的BUILD_ID变量。
3)引入(BUILD_SYSTEM)/version_defaults.mk的内容
/build/core/version_defaults.mk
即/build/core/version_defaults.mk,这里也主要是引入version_defaults.mk中的多个变量。
4)引入system_prop_file的内容
实际不存在
system_prop_file是在build.prop生成的末尾阶段以下面的方式引入的
system_prop_file自身是在该Makefile文件中定义的,如下:
经find命令搜索,TARGET_SYSTEM_PROP没有找到定义,所以走下一条路径,而TARGET_DEVICE_DIR在/build/core/config.mk中定义:
这段代码的意思TARGET_DEVICE_DIR就是Boardconfig.mk文件所在的目录,那么就应该是/device/hisilicon/Hi3798MV100
(注:
经过在Makefile中打印TARGET_DEVICE_DIR:
$(warning******TARGET_DEVICE_DIR:
$(TARGET_DEVICE_DIR)******),也确实是该目录
)。
所以这里就是要加载/device/hisilicon/Hi3798MV100下的system.prop,不过本平台在该目录下没有这个文件,所以system_prop_file的加载在这里是没有意义的
$(foreachfile,$(system_prop_file),\
warning***********system_prop1111file:
$(file)*************)
也确实打印不出任何目录)。
mr
5)引入ADDITIONAL_BUILD_PROPERTIES的内容
\build\core\product_config.mk
\device\hisilicon\Hi3798MV100\下的customer.mk和device.mk
\build\core\main.mk:
ADDITIONAL_BUILD_PROPERTIES是在build.prop生成的最后阶段以下面的方式引入的
ADDITIONAL_BUILD_PROPERTIES这个变量自身是在该Makefile文件中定义的,如下:
ADDITIONAL_BUILD_PROPERTIES最主要的作用就是引入另一个变量PRODUCT_PROPERTY_OVERRIDES,而这是在\build\core\product_config.mk中完成的:
ADDITIONAL_BUILD_PROPERTIES:
=\
$(ADDITIONAL_BUILD_PROPERTIES)\
$(PRODUCT_PROPERTY_OVERRIDES)
PRODUCT_PROPERTY_OVERRIDES的实际内容就很多了,它在\device\hisilicon\Hi3798MV100\下的customer.mk和device.mk,\build\core\main.mk等文件中都大量增加各种属性,也由此被引入到build.prop中。
如\device\hisilicon\Hi3798MV100\下的customer.mk下:
2.3其他属性文件
开机启动时,属性系统还要加载以下3个文件或目录,但是他们要么一般不使用(前2者),要么是运行时生成(后者)。
/*经验证,在3798MV100平台上并不存在*/
#definePROP_PATH_SYSTEM_DEFAULT"
/system/default.prop"
#definePROP_PATH_LOCAL_OVERRIDE"
/data/local.prop"
/*这是存储persist属性的目录,所有persist属性被各自写为文件存储在这里*/
#definePERSISTENT_PROPERTY_DIR"
/data/property"
3property的相关实现代码和流程
propertyservice运行于init进程中。
init进程首先创建一个共享内存区域,该内存实际是一个虚拟文件,打开并保存其fd。
init进程将该区域通过使用了MAP_SHARED标志的mmap映射至它自身的虚拟地址空间,这样,任何对于该区域的更新对于所有进程都是可见的。
fd和区域大小被存储在一个名为ANDROID_PROPERTY_WORKSPACE的变量中。
任何其他进程,比如consumer和setter将使用这个变量来获得fd和尺寸,这样它们就能mmap这个区域到它们自身的虚拟地址空间中。
该共享内存区域如下图所示:
3.1property服务端解析
3.1.1Server端代码流程
3.1.1.1init.c下的整体流程
代码路径:
\system\core\init\init.c
整个属性系统的server端都运行在init进程中,在该文件的main函数中有简明扼要的流程线索,见下面代码截图的8个要点:
下面仔细分析这8个环节。
3.1.1.2创建共享内存区域
经分析,实际该共享内存是通过共享文件+镜像内存看来实现的,只不过文件本身是虚拟设备文件,也活动在内存中,所以也可以理解为共享内存。
1)源头:
\system\core\init\init.c下的main函数:
2)进入\system\core\init\property_service.c:
进入property_init
进入init_property_area
3)进入\bionic\libc\bionic\system_properties.c
进入函数map_prop_area_rw:
特别注意:
a、mmap实现镜像内存
将文件和内存进行映射,文件内容对内存是透明的,同时对该内存的操作也会同步修改文件内容。
b、内存共享是变相实现,是共享文件+镜像内存,并非真正的共享内存。
从上面可以看出,android属性系统的property_area本质上不是共享内存,而是共享文件,各进程只是创建了对该文件的内存镜像,且只有init进程(中的pro[erty_service)的镜像具备写入权限。
(当然该文件也是内存中的虚拟文件,所以说是共享内存也说得过去,不过这是变相的,不是使用共享内存的相关API)。
4)进程间共享文件
从上面的分析可以看到:
a、这里共享内存是基于共享文件。
b、共享的文件是property_filename
\bionic\libc\include\sys\_system_properties.h下定义:
#definePROP_FILENAME"
/dev/__properties__"
\bionic\libc\bionic\system_properties.c下定义:
staticcharproperty_filename[PATH_MAX]=PROP_FILENAME;
c、操作property的进程间需要共享/dev/__properties__
那么/dev/__properties__文件到底是怎么共享的就需要被搞清楚了。
d、gcc之__libc_prenit特性实现文件共享
Android利用了gcc编译中的constructor属性,这个属性指明了一个__libc_prenit函数,当libc库被加载时,将自动调用这个__libc_prenit函数,android正是把/dev/__properties__的共享加入到这个函数内部,并进一步完成该共享文件到本地进程的映射工作。
简而言之,哪个进程加载libc,就加入了property系统的共享文件+镜像内存机制。
\bionic\libc\bionic\libc_init_dynamic.cpp
\bionic\libc\bionic\libc_init_common.cpp
5)\bionic\libc\bionic\system_properties.c
map_prop_area和map_prop_area_rw就只有文件打开方式,文件映射镜像内存的方式等方面的区别了
关于GCC中的constructor详细描述,请参照附录一《GCC中的constructor属性》
6)返回\system\core\init\property_service.c:
继续看init_property_area函数流程,进入:
再看init_workspace:
这个地方其实就是创建init进程下操作该共享文件的句柄而已,并保存在pa_workspace.全局变量中。
3.1.1.3加载根目录下的default.prop
2)进入\system\core\init\property_service.c
PROP_PATH_RAMDISK_DEFAULT在\bionic\libc\include\sys\_system_properties.h中定义:
#definePROP_PATH_RAMDISK_DEFAULT"
/default.prop"
注意加载属性的最后一步是把解析出来的属性通过property_set直接设置到镜像内存中,该函数的具体分析我们放到后面。
3.1.1.4加载其余4个属性文件的全部属性,并启动socket监听
1)源头
\system\core\init\init.c下的main函数:
将property_service_init_action标记为property_service_init加入到执行队列,在后面的while中去执行
\bionic\libc\include\sys\_system_properties.h中定义:
#definePROP_PATH_SYSTEM_BUILD"
/system/build.prop"
下面接着看property_service_init_action到底做了些什么
2)\system\core\init\init.c下的property_service_init_action
3)进入\system\core\init\property_service.c:
注意最后一个/data/property不是文件,是一个目录,下面每一个属性都存储为一个文件。
重点注意create_socket,这个函数要完成创建socket,绑定本地通讯端口等。
首先传入create_socket的PROP_SERVICE_NAME的定义:
\bionic\libc\include\sys\_system_properties.h中定义
#definePROP_SERVICE_NAME"
property_service"
create_socket中用到的ANDROID_SOCKET_DIR的定义:
\system\core\include\cutils\sockets.h
#defineANDROID_SOCKET_DIR"
/dev/socket"
4)进入\system\core\init\util.c
最终新创建的socket绑定到/dev/socket/property_service文件,实际就是localsocket的进程通讯模式。
3.1.1.5property触发器执行函数加入队列
将init.rc这里rc脚本文件解析出来的所有和property相关的触发器加入执行队列
2)\system\core\init\init.c下的queue_property_triggers_action
3)\system\core\init\init_parser.c中的queue_all_property_triggers
3.1.1.6执行队列中的property任务
源头:
进入execute_one_command:
不断通过外部循环获取队列中的action来执行。
注意这里面有一个隐藏任务:
当execute_one_command执行的是请一个service进程的时候,这里面还顺带完成了将proparea内存区的pa_workspace注册到环境变量的工作,以便其他进程也可以读取该变量。
3.1.1.7将property的监听socket加入待检查的socket数组
进入\system\core\init\property_service.c,这里get_property_set_fd返回的property_set_fd正是步骤3.1.1.4创建的监听socket。
3.1.1.8检查上层有哪些端口连接请求
3.1.1.9property设置的响应
2)进入\system\core\init\property_service.c的handle_property_set_fd
这里的知识点较多,需要仔细分析:
这里面对属性的设置出现了两个分支:
3)ctl开头的属性控制sercive的起停
ctl开头的属性,是用来支持上层对特定service进行起停控制的,check_control_perms会检查要控制的属性的权限,handle_control_message真正处理service的控制。
比如dhcp相关的一个处理:
:
init.3798MV100.rc脚本中定义了dhcp的服务:
iprenew_eth0
\system\core\libnetutils\dhcp_utils.c中dhcp_do_request_renew函数:
传递到\system\core\init\property_service.c的handle_property_set_fd中:
msg.name为ctl.start,msg.value为iprenew_eth0。
再进入到\system\core\init\init.c下的handle_control_message,
msg为start,args为iprenew_eth0,继续进入到msg_start,里面就是很熟悉的service的启动操作service_start了。
通过这样的流程,完成了对应应用层通过虚拟属性ctl控制系统服务的响应,ctl开头的属性本质上可以看成仅仅是通过socket发送的一种系统消息。
可以类推setprop
ctl.start
iprenew_eth0都能启动dhcp。
4)响应其他属性的setpprop请求
首先完成对上层请求setprop的进程的权限检查,权限足够就进入property_set,注意这个是server端property_service.c里面的property_set。
这里的权限检查函数,有助于我们理解哪些属性需要什么样的权限,再遇到上层无法设置某些属性的时候就能迅速知道原因了:
白名单如下:
根据这个列表,在应用程序apk中如果想设置某类属性,则只需要将该apk在主xml中设置对应的权限即可。
另外上下文安全策略相关的东西check_mac_perms见附录,和本文的主体关系不大,暂且略过。
至此,server端的属性初始化和设置响应流程就完成了。
3.1.2详解server端的property_set
相关源代码:
\system\core\init\property_service.c
\bionic\libc\bionic\system_properties.c
服务端的property_set流程控制实现在property_service.c中,但是其调用的函数实现都在
system_properties.c中,后者以libc.a库的形势被引入。
整个设置过程上面已经很清楚,其中有几个主要环节:
3.1.2.1__system_property_find
该函数的作用是根据属性名称找到该属性在镜像内存中的对应内存,并返回其数据指针*prop_info。
从这里可以看到,root_node返回的就是__system_property_area__->
data,即跳过了镜像内存的头信息之后的纯属性数据区首地址。
3.1.2.2find_property
接下来的find_property函数里面涉及到二叉树树形结构算法,技巧很强,阅读有一定难度。
从该函数可以看出当alloc_if_needed为true的时候,find_property同时承担了分配新属性的树形索引区prop_bt内存和真正的数据区内存prop_info的功能;
prop_info的真正地址就挂在末
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- android 系统 属性 详解