当前位置: 代码迷 >> Android >> Android-init过程(2)
  详细解决方案

Android-init过程(2)

热度:93   发布时间:2016-04-28 03:24:45.0
Android-init进程(2)
init属性服务就好比windows的注册表,应用可以对其应用信息进行属性操作

以下介绍属性服务的原理:


属性关键方法:
*void property_init(void)>>分析
void property_init(void){    init_property_area();}static int init_property_area(void){	prop_area *pa;	//创建共享内存	if(init_workspace(&pa_workspace, PA_SIZE))        return -1;	/**设置空间大小等其他信息*/	//系统自动调用__libc_prenit函数,完成共享内存到本地进程的工作	__system_property_area__ = pa;}

//通知其他进程
void __libc_preinit(void){	__libc_init_common(elfdata);}void __libc_init_common(uintptr_t *elfdata){	__system_properties_init();}int __system_properties_init(void){	//取出init创建环境变量获得文件描述符	env = getenv("ANDROID_PROPERTY_WORKSPACE");    fd = atoi(env);	//映射 init创建的内存到本地进程空间	//这样其他进程就可以共享这个内存了	//在这里 客户端只能做读取的操作	pa = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0);}

*void start_property_service(void)>>分析

1)加载属性文件到属性空间里面去 同时创建scoket

*void start_property_service(void){	//加载属性文件	load_properties_from_file(PROP_PATH_SYSTEM_BUILD);    load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);    load_override_properties();	//加载持久化文件    load_persistent_properties();	//创建socket	fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0);}init.c::int main(){	nr = poll(ufds, fd_count, timeout);	if (ufds[i].revents == POLLIN) {                if (ufds[i].fd == get_property_set_fd())                    handle_property_set_fd();				}	}}

2)main函数等待其他进程对该scoket调用并做出处理 修改属性
void handle_property_set_fd(){	//接收scoket    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {        return;    }    //取出进程的权限属性    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {        close(s);         return;    }		//接收数据	r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));		if(memcmp(msg.name,"ctl.",4) == 0) {            // ctl.* 控制消息	    //如setprop  ctl.start bootanim            close(s);            if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) {                handle_control_message((char*) msg.name + 4, (char*) msg.value);            } else {                ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",                        msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);            }    } else {	    //检查权限            if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) {	    //设置属性            property_set((char*) msg.name, (char*) msg.value);            } else {                ERROR("sys_prop: permission denied uid:%d  name:%s\n",cr.uid, msg.name);            }    }	 }int property_set(const char *name, const char *value){	prop_info *pi = (prop_info*) __system_property_find(name);		if(pi != 0) {        /* ro.* properties 只读属性 不能设置 */        if(!strncmp(name, "ro.", 3)) return -1;		//更新属性        update_prop_info(pi, value, valuelen);    } else {        //增加属性最多247项    }	//处理持久属性/net.*/	.....................	//修改属性同时执行的操作	property_changed(name, value);}

3)客户端创建scoket请求
//Android提供System.getProperty来获得属性服务。 以下以android2.3为例
/**SystemProperties.java*/

private static native String native_get(String key);    public static String get(String key) {        if (key.length() > PROP_NAME_MAX) {            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);        }        return native_get(key);    }

/**jni调用部分采用动态注册的 android_os_SystemProperties.cpp*/
static JNINativeMethod method_table[] = {		{ "native_get", "(Ljava/lang/String;)Ljava/lang/String;",		  (void*) SystemProperties_getS },		  		  .......//省略部分代码		}	}	static jstring SystemProperties_getS(JNIEnv *env, jobject clazz,jstring keyJ)	{		return SystemProperties_getSS(env, clazz, keyJ, NULL);	}	static jstring SystemProperties_getSS(JNIEnv *env, jobject clazz,jstring keyJ, jstring defJ)	{		int len;		const char* key;		char buf[PROPERTY_VALUE_MAX];		jstring rvJ = NULL;				.............//省略部分代码				key = env->GetStringUTFChars(keyJ, NULL);				len = property_get(key, buf, "");		//构造获得的属性		rvJ = env->NewStringUTF(buf);		.............	}

/**Properties.c*/ //查看property_get获取属性服务源码
int property_get(const char *key, char *value, const char *default_value)	{		char sendBuf[1+PROPERTY_KEY_MAX];		char recvBuf[1+PROPERTY_VALUE_MAX];		int len = -1;		...............		//执行init函数获取属性		pthread_once(&gInitOnce, init);		...............		return len;	}	static void init(void)	{		................		gPropFd = connectToServer(SYSTEM_PROPERTY_PIPE_NAME);		................	}	static int connectToServer(const char* fileName)	{		int sock = -1;		int cc;		struct sockaddr_un addr;		.................		/* connect to socket; fails if file doesn't exist */		//采用TCP连接服务器 定义地址和协议族AF_UNIX		strcpy(addr.sun_path, fileName);    // max 108 bytes		addr.sun_family = AF_UNIX;		cc = connect(sock, (struct sockaddr*) &addr, SUN_LEN(&addr));		if (cc < 0) {			close(sock);			return -1;		}		return sock;	}


  相关解决方案