Android System Property.docx

上传人:b****5 文档编号:7180704 上传时间:2023-01-21 格式:DOCX 页数:16 大小:161.21KB
下载 相关 举报
Android System Property.docx_第1页
第1页 / 共16页
Android System Property.docx_第2页
第2页 / 共16页
Android System Property.docx_第3页
第3页 / 共16页
Android System Property.docx_第4页
第4页 / 共16页
Android System Property.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

Android System Property.docx

《Android System Property.docx》由会员分享,可在线阅读,更多相关《Android System Property.docx(16页珍藏版)》请在冰豆网上搜索。

Android System Property.docx

AndroidSystemProperty

AndroidSystemProperty

一SystemProperty

  代码中大量存在:

SystemProperties.set()/SystemProperties.get();通过这两个接口可以对系统的属性进行读取/设置,

顾名思义系统属性,肯定对整个系统全局共享。

通常程序的执行以进程为单位各自相互独立,如何实现全局共享呢?

SystemProperties是怎么一回事,又是如何实现的呢?

      属性系统是android的一个重要特性。

它作为一个服务运行,管理系统配置和状态。

所有这些配置和状态都是属性。

每个属性是一个键值对(key/valuepair),其类型都是字符串。

这些属性可能是有些资源的使用状态,进程的执行状态,系统的特有属性……

      可以通过命令adbshell:

    getprop查看手机上所有属性状态值。

      或者getpropinit.svc.bootanim制定查看某个属性状态

      使用setpropinit.svc.bootanimstart设置某个属性的状态

特别属性:

  如果属性名称以“ro.”开头,那么这个属性被视为只读属性。

一旦设置,属性值不能改变。

  如果属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property。

  如果属性名称以“net.”开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名。

    (这是很巧妙的。

netresolve模块的使用这个属性来追踪在net.*属性上的任何变化。

  属性“ctrl.start”和“ctrl.stop”是用来启动和停止服务。

每一项服务必须在/init.rc中定义.系统启动时,与init守护

    进程将解析init.rc和启动属性服务。

一旦收到设置“ctrl.start”属性的请求,属性服务将使用该属性值作为服务

    名找到该服务,启动该服务。

这项服务的启动结果将会放入“init.svc.<服务名>“属性中。

客户端应用程序可以轮询那个属性值,以确定结果。

二framework访问系统服务流程

  framework通过SystemProperties接口操作系统属性,SystemProperties通过JNI调用访问系统属性。

  \frameworks\base\core\java\android\os\SystemProperties.java:

publicclassSystemProperties

{

//JNI

privatestaticnativeStringnative_get(Stringkey,Stringdef);

privatestaticnativevoidnative_set(Stringkey,Stringdef);

publicstaticStringget(Stringkey,Stringdef){

returnnative_get(key,def);

}

publicstaticvoidset(Stringkey,Stringval){

native_set(key,val);

}

}

Jni代码位置:

\frameworks\base\core\jni\android_os_SystemProperties.cpp

获取系统属性阻塞方式:

staticjstringSystemProperties_getSS()

{

len=property_get(key,buf,"");

操作在\bionic\libc\bionic\system_properties.c中:

int__system_property_get(constchar*name,char*value)

{

//数据已经存储在内存中__system_property_area__等待读取完返回

constprop_info*pi=__system_property_find(name);

return__system_property_read(pi,0,value);

      进程启动后数据已经将系统属性数据读取到相应的共享内存中,保存在全局变量__system_property_area__;

进程之间都是独立的,系统属性数据是如何读取到当前进程空间中的呢?

后续介绍。

设置属性异步socket通信:

int__system_property_set(constchar*key,constchar*value)

{

msg.cmd=PROP_MSG_SETPROP;

strlcpy(msg.name,key,sizeofmsg.name);

strlcpy(msg.value,value,sizeofmsg.value);

err=send_prop_msg(&msg);

}

staticintsend_prop_msg(prop_msg*msg)

{

//sokcet通信/dev/socket/property_service

s=socket(AF_LOCAL,SOCK_STREAM,0);

connect(s,(structsockaddr*)&addr,alen)

send(s,msg,sizeof(prop_msg),0)

close(s);

}

  通过socket向property_service发送消息,property_service运行在哪里呢?

三PropertyService创建服务端socket

init进程启动监听过程中:

\system\core\init\Init.c

intmain(intargc,char**argv)

{

//加入到actionqueue队列

queue_builtin_action(property_service_init_action,"property_service_init");

for(;;)

//执行actionqueue队列

//接收通过socket向propertyservice发送的数据;

nr=poll(ufds,fd_count,timeout);

……

handle_property_set_fd();

}

staticintproperty_service_init_action(intnargs,char**args)

{

start_property_service();

}

\system\core\init\property_service.c:

voidstart_property_service(void)

{

//加载属性配置文件

load_properties_from_file(PROP_PATH_SYSTEM_BUILD);

load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);

load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);

load_persistent_properties();

//创建socket资源并绑定

fd=create_socket(PROP_SERVICE_NAME,SOCK_STREAM,0666,0,0);

//监听

listen(fd,8);

}

  PropertyService是运行在init守护进程中。

  接收到消息之后干什么,还是要先弄清楚整个PropertyService是如何实现的呢,后续介绍。

先看看PropertyService接收到消息后的处理。

 

四PropertyService监听socket处理

PropertyService监听socket消息的处理过程:

voidhandle_property_set_fd()

{

//等待建立通信

s=accept(property_set_fd,(structsockaddr*)&addr,&addr_size)

//获取套接字相关信息uidgid

getsockopt(s,SOL_SOCKET,SO_PEERCRED,&cr,&cr_size);

//接收属性设置请求消息

recv(s,&msg,sizeof(msg),0);

//处理消息

switch(msg.cmd){

casePROP_MSG_SETPROP:

//通过设置系统属性处理ctl.开头消息

if(memcmp(msg.name,"ctl.",4)==0)

{

//权限检测

if(check_control_perms(msg.value,cr.uid,cr.gid))

{

handle_control_message((char*)msg.name+4,(char*)msg.value);

}

}else

{

//更改系统属性值

if(check_perms(msg.name,cr.uid,cr.gid))

{

property_set((char*)msg.name,(char*)msg.value);

}

}

break;

}

close(s);

}

通过设置系统属性启动/关闭Service:

权限判断:

staticintcheck_control_perms(constchar*name,unsignedintuid,unsignedintgid)

{

//system/root用户直接有权限

if(uid==AID_SYSTEM||uid==AID_ROOT)

return1;

//查询用户名单,判断是否存在表中并具有对应权限

for(i=0;control_perms[i].service;i++){

if(strcmp(control_perms[i].service,name)==0){

if((uid&&control_perms[i].uid==uid)||

(gid&&control_perms[i].gid==gid)){

return1;

}

}

}

return0;

}

 

 所以如果想要应用有权限启动/关闭某NativeService:

  需要具有system/root权限

  找到对应应用uidgid,将应用名称加入到control_perms列表中

 

处理消息可以通过设置系统属性改变服务的执行状态start/stop:

voidhandle_control_message(constchar*msg,constchar*arg)

{

if(!

strcmp(msg,"start")){

msg_start(arg);

}elseif(!

strcmp(msg,"stop")){

msg_stop(arg);

}elseif(!

strcmp(msg,"restart")){

msg_stop(arg);

msg_start(arg);

}

}

staticvoidmsg_start(constchar*name)

{

service_start(svc,args);

}

voidservice_start(structservice*svc,constchar*dynamic_args){

//创建进程启动服务

pid=fork();

execve(svc->args[0],(char**)svc->args,(char**)ENV);

//修改服务的系统属性执行状态

notify_service_state(svc->name,"running");

}

连着前面就是ctr.start和ctr.stop系统属性:

用来启动和停止服务的。

例如:

    //startbootanimation

    property_set("ctl.start","bootanim");

在init.rc中表明服务是否在开机时启动:

serviceadbd/sbin/adbd

    classcore

    disabled//不自动启动

 

启动服务的时候会判断:

staticvoidservice_start_if_not_disabled(structservice*svc)

{

//判断是否启动

if(!

(svc->flags&SVC_DISABLED)){

service_start(svc,NULL);

}

}

修改系统属性值:

staticintcheck_perms(constchar*name,unsignedintuid,unsignedintgid)

{

//进行权限检测

for(i=0;property_perms[i].prefix;i++){

inttmp;

if(strncmp(property_perms[i].prefix,name,

strlen(property_perms[i].prefix))==0){

if((uid&&property_perms[i].uid==uid)||

(gid&&property_perms[i].gid==gid)){

return1;

}

}

}

return0;

}

 

看这个修改系统属性权限表:

property_perms[]={

{"net.dns",AID_RADIO,0},

{"net.",AID_SYSTEM,0},

{"dev.",AID_SYSTEM,0},

{"runtime.",AID_SYSTEM,0},

{"sys.",AID_SYSTEM,0},

{"service.",AID_SYSTEM,0},

{"persist.sys.",AID_SYSTEM,0},

{"persist.service.",AID_SYSTEM,0},

……

{NULL,0,0}

};

 

  指定了特定的用户有用修改带有某些前缀的系统属性值。

  到这里基本就是Property对外的基本工作流程,PropertyService内部具体如何实现,操作运行,

  跨进程空想内存等问题仍未清除是如何处理的。

五属性系统设计

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

     

  PropertyService运行在init进程中,开机从属性文件中加载到共享内存中;设置系统属性通过socket与PropertyService通信。

  PropertyConsumer进程将存储系统属性值的共享内存,加载到当前进程虚拟空间中,实现对系统属性值的读取。

  PropertySetter进程修改系统属性,通过socket向PropertyService发送消息,更改系统属性值。

六属性系统实现

      属性系统设计的关键就是:

跨进程共享内存的实现。

下面将看看属性系统实现具体过程:

Init进程执行:

intmain(intargc,char**argv){

//将属性系统初始化函数加入actionqueue

  queue_builtin_action(property_init_action,"property_init");

  for(;;)

}

staticintproperty_init_action(intnargs,char**args)

{

property_init(load_defaults);

}

初始化PropertyService:

      \system\core\init\property_service.c

voidproperty_init(boolload_defaults)

{

//初始化共享内存空间

init_property_area();

//加载属性文件

  load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT);

}

初始化共享内存空间:

staticintinit_property_area(void)

{

//创建匿名内存空间PA_SIZE=32768

init_workspace(&pa_workspace,PA_SIZE)

//将内存区域分成两部分:

属性系统基本信息和属性键值对

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;

/*plugintothelibpropertyservices*/

__system_property_area__=pa;

}

__system_property_area__:

  每个进程都会使用此变量,指向系统属性共享内存区域,访问系统属性,很重要。

位于:

\bionic\libc\bionic\system_properties.c中,属于bionic库。

后面将介绍各进程如何加载共享内存。

将文件作为共享内存映射到进程空间内存使用:

staticintinit_workspace(workspace*w,size_tsize)

{

//devisatmpfs是一种虚拟内存文件系统

intfd=open("/dev/__properties__",O_RDWR|O_CREAT,0600);

//将文件映射为共享进程空间内存使其可以与操作内存方式一致

void*data=mmap(NULL,size,PROT_READ|PROT_WRITE,

      MAP_SHARED,fd,0);

close(fd);

//删除文件

fd=open("/dev/__properties__",O_RDONLY);

unlink("/dev/__properties__");

//保存fdsize将作为环境变量传递给每个进程

w->data=data;w->size=size;w->fd=fd;

}

加载系统属性默认数据文件:

#definePROP_PATH_RAMDISK_DEFAULT"/default.prop"

staticvoidload_properties_from_file(constchar*fn)

{

//读取系统属性键值对数据写入到共享内存中

data=read_file(fn,&sz);

load_properties(data);

  加上上面所述:

PropertyServiceSocket资源的创建,来监听socket通信连接设置系统属性,

  在Init进程中PropertyService完成了初始化。

将得到该内存区域数据结构:

     

七进程共享系统属性内存空间实现

  PropertyService运行于init进程中,将文件映射为创建一块共享内存空间,但在整个系统中,

其他进程也能够读取这块内存映射到当前进程空间中,是如何实现的呢?

Service进程启动:

将共享内存空间fdsize作为环境变量传递给新创建进程

voidservice_start(structservice*svc,constchar*dynamic_args)

{

//创建进程

pid=fork();

if(pid==0){

if(properties_inited()){

//获取系统属性空间文件描述

get_property_workspace(&fd,&sz);

//dup最小的可用文件描述符

sprintf(tmp,"%d,%d",dup(fd),sz);

//加入ANDROID_PROPERTY_WORKSPACE环境变量到ENV

        //包含共享内存fd

add_environment("ANDROID_PROPERTY_WORKSPACE",tmp);

}

//执行程序传递环境变量ENV

execve(svc->args[0],(char**)svc->args,(char**)ENV)

//设置Service系统属性

notify_service_state(svc->name,"running");

}

}

voidget_property_workspace(int*fd,int*sz)

{

*fd=pa_workspace.fd;

*sz=pa_workspace.size;

}

共享内存空间fdsize作为环境变量传递给新创建进程后,将在何处使用呢?

将系统属性内存空间映射到当前进程虚拟空间:

进程在启动时,会加载动态库bioniclibc库:

  \bionic\libc\bionic\libc_init_dynamic.c中:

  void__attribute__((constructor))__libc_preinit(void);          

根据GCC的constructor/destructor属性:

    给一个函数赋予constructor或destructor,其中constructor在main开始运行之前被调用,

  destructor在main函数结束后被调用。

如果有多个constructor或destructor,可以给每个constructor

  或destructor赋予优先级,对于constructor,优先级数值越小,运行越早。

destructor则相反。

多个constructor需要加优先级:

__attribute__((constructor

(1)))void

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1