http://blog.csdn.net/angelbosj/article/details/7981247

 

Android Property System | Android属性系统(文章写的很好。)

标签: androidsystempropertiesmakefilesetter
  4264人阅读  评论(1)  收藏  举报
  分类:
 
  

Android Property System | Android属性系统

分类: Android frameworks   196人阅读  评论(0)  收藏  举报

  从shell中得到属性值: getprop 


属性系统是Android的一个重要特性。它作为一个服务运行,管理系统配置和状态。所有这些配置和状态都是属性。每个属性是一个键值对(key/value pair),其类型都是字符串。

         从功能上看,属性与windows系统的注册表非常相似。许多android应用程序和库直接或者间接地依赖此特性,以决定它们的运行时行为。例如,adbd进程查询属性服务已确认当前是否运行在模拟器环境中。另一个例子是Java.io.File.pathSpearator,其返回存储于属性服务中的值。

         属性系统是如何工作的

         属性系统的上层架构如下图所示。

         图中有3个进程、一组永久属性文件和一块共享内存区域。共享内存区域是所有属性记录的存储所在。只有属性服务进程才可以写入共享内存区域,它负责从永久文件中加载属性记录并将它们保存在共享内存中。

         consumer进程将共享内存加载到其自身的虚拟地址空间并直接访问这些属性。setter进程同样将共享内存加载到其自身的虚拟地址空间,但其不能直接写该内存。当setter试图增加或者更新一个属性时,它将该属性通过unix domain socket发送至属性服务。属性服务代表setter进程将该属性写入共享内存和永久文件中。

         属性服务运行于init进程中。init进程首先创建一个共享内存区域,并保存一个指向该区域的描述符fd。init进程将该区域通过使用了MAP_SHARED标志的mmap映射至它自身的虚拟地址空间,这样,任何对于该区域的更新对于所有进程都是可见的。fd和区域大小被存储在一个名为ANDROID_PROPERTY_WORKSPACE的变量中。任何其他进程,比如consumer和setter将使用这个变量来获得fd和尺寸,这样它们就能mmap这个区域到它们自身的虚拟地址空间中。该共享内存区域如下图所示。

在这之后,init进程将从下列文件加载属性:

/default.prop
/system/build.prop
/system/default.prop
/data/local.prop

下一步是启动属性服务。在这一步中,一个unixdomain socket服务被创建。此socket的路径是/dev/socket/property_service,该路径对于其他客户端进程是熟知的。最后,init进程调用poll来等待该socket上的连接事件。

         在consumer一边,当它初始化libc(bionic/libc/bionic/libc_common.c__libc_init_common 函数),它将从环境变量中返回fd和尺寸,并映射共享内存到其自身的地址空间(bionic/libc/bionic/system_properties.c __system_properties_init 函数)。在这之后,libcutils可以想读取普通内存那样为consumer读取属性。

         目前,属性是不能够被删除的。也就是说,一旦添加了一个属性,它将不能够被删除,其键也不能够被改变。

         如何读取/设置属性

         Android上有三种主要途径来get/set属性。

1、  native code

当编写本地应用程序时,可以使用property_get和property_set 这两个API来读取/设置属性。要使用它们,我们需要include cutils/properties.h,并链接libcutils库。

2、  java code

在Java包(java.lang.System)中提供有System.getProperty和System.setProperty方法。但值得注意的是,尽管这两个API在语义上等同native函数,但其将数据存储于完全不同的位置。实际上,dalvik VM使用一个哈希表来存储这些属性。所以,用这两个API存储的属性是独立的,不能存取native属性,反之亦然。

然而Android有一个内部隐藏类(@hide,对SDK不可见)android.os.SystemProperties来操纵native属性。其通过jni来存取native属性库。

3、  shell脚本

Android提供getprop和setprop命令行工具来获取和更新属性。其依赖libcutils实现。

 

以上翻译自http://rxwen.blogspot.com/2010/01/android-property-system.html,有修正。


         补充:通过查看property_service.c,我们可以明确以下事实:

1、  属性名不是随意取的。在property_perms数组中定义了当前系统上可用的所有属性的前缀,以及相对应的存取权限UID。对属性的设置要满足权限要求,同时命名也要在这些定义的范围内。

2、  PA_COUNT_MAX指定了系统(共享内存区域中)最多能存储多少个属性。

3、  PROP_NAME_MAX指定了一个属性的key最大允许长度;PROP_VALUE_MAX则指定了value的最大允许长度。


由于对Android 的属性系统不是很了解,所以翻译了这篇文章《Android Property System》

每个属性都有一个名称和值,他们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性。
在系统初始化时,Android将分配一个共享内存区来存储的属性。这些是由“init”守护进程完成的,其源代码位于:device/system/init。“init”守护进程将启动一个属性服务。属性服务在“init”守护进程中运行。每一个客户端想要设置属性时,必须连接属性服务,再向其发送信息。属性服务将会在共享内存区中修改和创建属性。任何客户端想获得属性信息,可以从共享内存直接读取。这提高了读取性能。
客户端应用程序可以调用libcutils中的API函数以GET/SET属性信息。libcutils的源代码位于:device/libs/cutils。API函数是:
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
而libcutils又调用libc中的 __system_property_xxx 函数获得共享内存中的属性。libc的源代码位于:device/system/bionic。
属性服务调用libc中的__system_property_init函数来初始化属性系统的共享内存。当启动属性服务时,将从以下文件中加载默认属性:
/ default.prop
/system/build.prop
/system/default.prop
/data/local.prop
属性将会以上述顺序加载。后加载的属性将覆盖原先的值。这些属性加载之后,最后加载的属性会被保持在/data/property中。

 特别属性
如果属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变。
如果属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property。
如果属性名称以“net.”开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名。(这是很巧妙的。 netresolve模块的使用这个属性来追踪在net.*属性上的任何变化。)
属性“ ctrl.start ”和“ ctrl.stop ”是用来启动和停止服务。每一项服务必须在/init.rc中定义.系统启动时,与init守护进程将解析init.rc和启动属性服务。一旦收到设置“ ctrl.start ”属性的请求,属性服务将使用该属性值作为服务名找到该服务,启动该服务。这项服务的启动结果将会放入“ init.svc.<服务名>“属性中 。客户端应用程序可以轮询那个属性值,以确定结果。

Android toolbox程序
Android toolbox程序提供了两个工具: setprop和getprop获取和设置属性。其使用方法:
getprop <属性名>
setprop <属性名><<属性值>

Java
在Java应用程序可以使用System.getProperty()和System.setProperty()函数获取和设置属性。

Action
默认情况下,设置属性只会使"init"守护程序写入共享内存,它不会执行任何脚本或二进制程序。但是,您可以将您的想要的实现的操作与init.rc中某个属性的变化相关联.例如,在默认的init.rc中有:

    # adbd on at boot in emulator
    on property:ro.kernel.qemu=1
       start adbd
    on property:persist.service.adb.enable=1
       start adbd
    on property:persist.service.adb.enable=0
       stop adbd

这样,如果你设置persist.service.adb.enable为1 ,"init"守护程序就知道需要采取行动:开启adbd服务。

 

 

 

文章中提到的共享内存就是Android特有的共享方式:ashmen

Ashmem是一个匿名共享内存(Anonymous SHaredMEMory)系统,该系统增加了接口因此进程间可以共享具名内存块。举一个例子,系统可以利用Ashmem存储图标,当绘制用户界面的时候多个进程也可以访问。Ashmem优于传统Linux共享内存表现在当共享内存块不再被用的时候,它为Kernel提供一种回收这些共享内存块的手段。如果一个程序尝试访问Kernel释放的一个共享内存块,它将会收到一个错误提示,然后重新分配内存并重载数据。


android属性之build.prop生成过程分析

本文简要分析一下build.prop是如何生成的。Android的build.prop文件是在Android编译时刻收集的各种property(LCD density/语言/编译时间, etc.),编译完成之后,文件生成在out/target/product/<board>/system/目录下。在Android运行时刻可以通过property_get()[c/c++域] / SystemProperties_get*()[Java域]读取这些属性值。


build.prop的生成是由make系统解析build/core/Makefile完成。

1)      Makefile中首先定义各种变量,这在下一步执行时会用到。比如:

 
view plain

    ...  
    PRODUCT_DEFAULT_LANGUAGE="$(calldefault-locale-language,$(PRODUCT_LOCALES))" \  
    PRODUCT_DEFAULT_REGION="$(calldefault-locale-region,$(PRODUCT_LOCALES))" \  
    ...  

2)      Makefile中调用build/tools/buildinfo.sh执行脚本,并输出到build.prop

Buildinfo.sh很简单,只是echo一些属性,比如:

 
view plain

    ...  
    echo"ro.product.locale.language=$PRODUCT_DEFAULT_LANGUAGE"  
    echo"ro.product.locale.region=$PRODUCT_DEFAULT_REGION"  
    ...  

而,ro.product.locale.language/ ro.product.locale.region就是些属性,等号后面是值。

3)      Makefile中直接把$(TARGET_DEVICE_DIR)/system.prop的内容追加到build.prop中。

4)      收集ADDITIONAL_BUILD_PROPERTIES中的属性,追加到build.prop中。

ADDITIONAL_BUILD_PROPERTIES又会收集PRODUCT_PROPERTY_OVERRIDES中定义的属性

 
view plain

    ADDITIONAL_BUILD_PROPERTIES:= \  
            $(ADDITIONAL_BUILD_PROPERTIES)\  
            $(PRODUCT_PROPERTY_OVERRIDES)  

 

通过build.prop生成过程的分析,可知哪里可以修改原有的属性或加入自己定义属性,那就是2) buildinfo.sh; 3) system.prop; 4) ADDITIONAL_BUILD_PROPERTIES或PRODUCT_PROPERTY_OVERRIDES。不过个人建议改在system.prop或PRODUCT_PROPERTY_OVERRIDES,这对应于具体特定平台或产品的修改

1
0
 
 
我的同类文章

参考知识库

img
Android知识库

img
大型网站架构知识库

img
Java EE知识库

img
Java SE知识库

img
Java Web知识库

猜你在找
Android底层技术:Java层系统服务(Android Service)
Android开发精品课程【Java核心知识】
Android必备的Java基础知识(二)
Ceph—分布式存储系统的另一个选择
Android入门实战教程
id="iframeu1607657_0" src="http://pos.baidu.com/jctm?sz=728x90&rdid=1607657&dc=2&di=u1607657&dri=0&dis=0&dai=2&ps=6844x405&coa=at%3D3%26rsi0%3D728%26rsi1%3D90%26pat%3D6%26tn%3DbaiduCustNativeAD%26rss1%3D%2523FFFFFF%26conBW%3D1%26adp%3D1%26ptt%3D0%26titFF%3D%2525E5%2525BE%2525AE%2525E8%2525BD%2525AF%2525E9%25259B%252585%2525E9%2525BB%252591%26titFS%3D%26rss2%3D%2523000000%26titSU%3D0%26ptbg%3D90%26piw%3D0%26pih%3D0%26ptp%3D0&dcb=BAIDU_SSP_define&dtm=HTML_POST&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1468978322458&ti=Android%20Property%20System%20%7C%20Android%E5%B1%9E%E6%80%A7%E7%B3%BB%E7%BB%9F(%E6%96%87%E7%AB%A0%E5%86%99%E7%9A%84%E5%BE%88%E5%A5%BD%E3%80%82)%20-%20Bob%E7%9A%84%E4%B8%93%E6%A0%8F%20-%20%E5%8D%9A%E5%AE%A2&ari=2&dbv=2&drs=3&pcs=1349x630&pss=1349x7740&cfv=16&cpl=32&chi=3&cce=true&cec=UTF-8&tlm=1468978322&rw=630&ltu=http%3A%2F%2Fblog.csdn.net%2Fangelbosj%2Farticle%2Fdetails%2F7981247&ecd=1&psr=1366x768&par=1366x728&pis=-1x-1&ccd=24&cja=true&cmi=49&col=zh-CN&cdo=-1&tcn=1468978322&qn=3b0ee316b1ffc939&tt=1468978322384.98.362.372" width="728" height="90" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="border-width: 0px; vertical-align: bottom; margin: 0px;">
查看评论
1楼  堕落方能自由 2015-05-08 17:19发表 [回复]
不明觉厉
发表评论
  • 用 户 名:
  • veryliu
  • 评论内容:
  • 插入代码
  •   
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
  • 博客专栏
  • 个人资料
  •  
    1
    • 访问:172115次
    • 积分:2664
    • 等级: 
    • 排名:第9319名
    • 原创:85篇
    • 转载:35篇
    • 译文:0篇
    • 评论:96条
  • 文章存档
  • 最新评论
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值