Android 属性系统设计分析

原创 2012年03月29日 14:06:46
Android 属性系统设计分析


前面已经讲过 "Android 属性系统 Property service 设定分析" ,请参考


这篇博文主要讲解其属性系统的设计原理与思想方法,前一篇是实践,这一篇是理论,本质性原理。

首先看下整个属性系统结构图:



属性读取进程(property consumer)把这块共享内存映射到自己的进程空间,然后直接读取它。属性设置进程(property setter)也加载这块共享到他的进程空间,但是他不能直接写这块共享内存。当他需要增加或者修改属性的时候,通过Unix Socket发生属性给Property service,Property service将代表设置进程写入共享内存和属性文件。


1、属性服务初始化:

main @ /system/core/init  调用 property_init();

void property_init(void)
{
    init_property_area();
    
    // 加载默认 default.prop 文件
    load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT);
}


属性服务代码: /system/core/init/property_service.c

static int init_property_area(void)

{

    // 1、 创建一块用于存储属性的存储区域,其实就是一块匿名内存空间

    if(init_workspace(&pa_workspace, PA_SIZE))

    return -1;


    fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC);


    pa_info_array = (void*) (((char*) pa_workspace.data) + PA_INFO_START);


    pa = pa_workspace.data;
    memset(pa, 0, PA_SIZE);
    pa->magic = PROP_AREA_MAGIC;
    pa->version = PROP_AREA_VERSION;

   // 这是由 bionic libc 库定义,大有来头哟,也是其它进程能够访问属性系统的关键所在

   /* plug into the lib property services */

   __system_property_area__ = pa;

}


以上代码建立的共享内存布局如下:



2、Property区域共享问题

Property service运行于init进程中,这里创建一块共享内存空间,但android系统希望其它进程也能够读取到这里内存中的内容,这里如何做到的呢?

A、属性系统内存区域建立于共享内存上,跨进程可以使用。由init_workspace()函数完成
B、利用linux的环境变量传递参数,这里传递 fd 及 size 
service_start @ /system/core/init
void service_start(struct service *svc, const char *dynamic_args)

{

   // 新的进程创建

     pid = fork();

     if (pid == 0) {

        ...
        get_property_workspace(&fd, &sz);
        // 注意这里哟,不同的进程需要使用必须首先dup(fd)值,最开始的 fd = 4 ,size = 32768
        sprintf(tmp, "%d,%d", dup(fd), sz);
        
        // 注意这个环境变量: "ANDROID_PROPERTY_WORKSPACE" 后面会使用到
        add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
        
}


这里就是获取创建空间内存空间时的 fd 及 size 参数值
void get_property_workspace(int *fd, int *sz)
{
   *fd = pa_workspace.fd;
   *sz = pa_workspace.size;
}


C、利用 gcc 的 Contructor 属性
/* We flag the __libc_preinit function as a constructor to ensure
* that its address is listed in libc.so's .init_array section.
* This ensures that the function is called by the dynamic linker
* as soon as the shared library is loaded.
*/
void __attribute__((constructor)) __libc_prenit(void);

每个进程启动时都需要加载 bionic libc 库,那么这个函数将会一定自动执行,而这里将完成将属性共享内存空间映射到本地进程的内存空间。

__libc_prenit @ /bionic/libc/bionic/libc_init_dynamic.c

void __libc_prenit(void)
{
__libc_init_common(elfdata);
}
-->
void __libc_init_common(uintptr_t *elfdata)

{

    /* setup system properties - requires environment */

    __system_properties_init();

}


ok,现在看看我们重点关注的函数:

__system_properties_init @ /bionic/libc/bionic/system_properties.c


int __system_properties_init(void)
{
	prop_area *pa;
	int s, fd;
	unsigned sz;
	char *env;

	if(__system_property_area__ != ((void*) &dummy_props)) {
		return 0;
	}

	// 1、这里利用init进程中设定的环境变量 "ANDROID_PROPERTY_WORKSPACE"获取fd及size值   
	env = getenv("ANDROID_PROPERTY_WORKSPACE");
	if (!env) {
		return -1;
	}
	fd = atoi(env);
	env = strchr(env, ',');
	if (!env) {
		return -1;
	}
	sz = atoi(env + 1);

	// 本地进程映射属性内存空间,如此本地进程就可以使用这块共享内存,只能读取(PROT_READ)
	pa = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0);

	if(pa == MAP_FAILED) {
		return -1;
	}

	if((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION)) {
		munmap(pa, sz);
		return -1;
	}

	// ok, __system_property_area__ 指向共享内存首地址
	__system_property_area__ = pa;
	return 0;
}

可以在 __system_properties_init 函数加打印 env 值,发现有新的进程加载bionic libc时,其值依次为:

__system_properties_init env = 4,32768

__system_properties_init env = 5,32768

__system_properties_init env = 6,32768

__system_properties_init env = 7,32768

__system_properties_init env = 8,32768

__system_properties_init env = 9,32768

因为在 init 进程中每次更新环境变量,dup(fd)值所以发生变化。


3、Property service 接收设置请求,利用socket请求,前面已经讲过就不复述了。


4、Property 属性系统使用
Native代码主要接口:
/system/core/libcutils/properties.c
int property_get(const char *key, char *value, const char *default_value);
int property_set(const char *key, const char *value);
int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie);    


JAVA代码主要接口,存在两种访问方式:

libcore下面的System.java 

System.getProperty(String prop,String defaultValue);
SystemsetProperty(String prop, String value);

/**
* Internal class holding the System properties. Needed by the Dalvik VM for the
* two native methods. Must not be a local class, since we don't have a System
* instance.
*/
class SystemProperties extends Properties {
   // Dummy, just to make the compiler happy.

   native void preInit();

   native void postInit();
}

libcore下面的Properties.java
public class Properties extends Hashtable<Object, Object>

注意:这层属性操作的接口利用JVM中hash表来维护Java的属性

另处一种方式就是 通过framworks下面的 SystemProperties.java 利用jni操作属性系统
getXXX 及 set 函数

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android 属性系统设计分析

http://blog.csdn.net/andyhuabing/article/details/7406930 Android 属性系统设计分析 前面已经讲过 "Android 属性...
  • zangchaodotcnatgmail
  • zangchaodotcnatgmail
  • 2016年04月09日 15:37
  • 250

图床上传系统设计分析

女主宣言在本篇文章中,女主就带大家去分析一下图床系统的上传模块的设计与实现,让大家能够更清晰的了解,图床系统是如何支撑各业务每天数以千万级的图片上传的。PS:丰富的一线技术、多元化的表现形式,尽在“H...
  • ZVAyIVqt0UFji
  • ZVAyIVqt0UFji
  • 2018年02月01日 00:00
  • 43

电商秒杀系统设计分析

1,乐视秒杀,每秒钟10万的订单更新(insert/update),以用户ID分库分表,二叉树分库扩容,表级同步,DB1 - DB8, order1 - order10, DB编号 = (uid/10...
  • zhanjianshinian
  • zhanjianshinian
  • 2016年11月26日 00:32
  • 2787

Dota2技能系统设计分析

前两周写完了新游戏的技能系统。虽然也算灵活,但是跟Dota2的技能系统设计比起来,就差了很多。无论从灵活性还是功能实现上,其技能系统设计的都相当漂亮。如果早一些分析它的技能系统的话,我想我可以实现的更...
  • langresser
  • langresser
  • 2015年07月06日 17:35
  • 3257

android 平台自定义可读写的ro属性

1、将flash作为一个媒介,进行这些属性的存储 2、上次集成了nand的一些命令,通过这些命令,我们可以从flash里面将数据读取出来 3、通过一系列的解析操作,将数据整理成我们可操作的内存结构...
  • zvivi521
  • zvivi521
  • 2013年08月02日 14:43
  • 1001

知乎产品分析|知识社区何去何从

一、引言   2017年2月,知乎月独立用户设备数再次回升,相比1月上涨了11.2%,达到了1109万台。 1.1目的 通过对知乎这款产品的分析,锻炼自己的思维能力,深化自己对产品的理...
  • liang19960530
  • liang19960530
  • 2017年04月20日 10:41
  • 2327

Android属性系统简介

原文:https://www.cnblogs.com/l2rf/p/6610348.html 1、简介   在android 系统中,为统一管理系统的属性,设计了一个统一的属性系统。每...
  • gaobaoshen1
  • gaobaoshen1
  • 2017年11月28日 16:48
  • 88

链表(算法分析与设计笔记)

链表中的数据元素的地址是任意的。 连表示一组数据元素的集合,期中每个数据元素都是一个结点,结点的数据部分称为结点的数据域。为了能对整个链表惊醒遍历或访问,链表的每个节点至少还应该包含一个指向它的直接...
  • ChinMint
  • ChinMint
  • 2016年08月24日 14:10
  • 406

Android调用系统剪裁参数

裁剪框比例: intent.putExtra("aspectX", 3); intent.putExtra("aspectY", 2); 输出图片大小: intent.putExtra("output...
  • u014765620
  • u014765620
  • 2016年07月18日 13:54
  • 727

学生信息管理系统总结——系统设计分析

无论是做什么事情,首先要学会一件事,那就是要把握宏观,树立全局意识!不谋全局者不足某一域,不谋万世者不足以谋一时!对于学生信息管理系,先让我们做个大概的宏观导图。      在这个系统中,大概...
  • u011500356
  • u011500356
  • 2014年08月05日 21:11
  • 1652
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android 属性系统设计分析
举报原因:
原因补充:

(最多只允许输入30个字)