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;
	}

时间: 2024-10-21 16:39:26

Android-init进程(2)的相关文章

Android -- Init进程对信号的处理流程

Android -- Init进程对信号的处理流程 在Android中,当一个进程退出(exit())时,会向它的父进程发送一个SIGCHLD信号.父进程收到该信号后,会释放分配给该子进程的系统资源:并且父进程需要调用wait()或waitpid()等待子进程结束.如果父进程没有做这种处理,且父进程初始化时也没有调用signal(SIGCHLD, SIG_IGN)来显示忽略对SIGCHLD的处理,这时子进程将一直保持当前的退出状态,不会完全退出.这样的子进程不能被调度,所做的只是在进程列表中占据

android init进程分析 init脚本解析和处理

(懒人近期想起我还有csdn好久没打理了.这个android init躺在我的草稿箱中快5年了.略微改改发出来吧) RC文件格式 rc文件是linux中常见的启动载入阶段运行的文件.rc是run commands的缩写.基本上能够理解为在启动阶段运行的一些列命令.android init进程启动时,也会运行此启动脚本文件,init.rc.init.rc的写法稍有点复杂,具体可參考 /system/core/init下的readme文件.脚本基本组成是由四类,为: commands: 命令 act

android init进程分析

android的init进程用来启动zygote进程,用来启动android世界.init进程的源码在顶层目录的/system/core/init使用 find -name Android.mk -exec grep -l "init" {} \;来查找源码,接下来的android服务程序也是使用这个指令来查找源码. /system/core/init/init.c 整个init进程的入口函数669 int main(int argc, char **argv) init_parse_

Android init进程概述

init进程,其程序位于根文件系统中,在kernle自行启动后,其中的 start_kernel 函数把根文件系统挂载到/目录后,在 rest_init 函数中通过 kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); 建立PID为1的内核进程,随后调用 run_init_process 来加载boot分区中根文件系统里的init程序来跳转到用户空间运行.init是第一个运行在用户空间的进程.之后很多的系统服务都由init进程fo

Android init进程——属性服务

目录 目录 概述 属性服务 属性服务初始化 创建存储空间 __system_property_area_init init_workspace 客户端进程访问属性内存区域 属性服务器的分析 启动属性服务器 服务端处理设置属性请求 客户端发送请求 概述 init是一个进程,确切的说,它是Linux系统中用户空间的第一个进程.由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程.init的进程号是1.作为天字第一号进程,init有很多重要的工作: ini

Android init进程——源码分析

概述 Android本质上是一个基于Linux内核的开源操作系统,与我现在用的Ubuntu系统类似,但是所有的Android设备都是运行在ARM处理器(ARM源自进阶精简指令集机器,源自ARM架构)上,而像Ubuntu操作系统是x86(x86是一系列的基于intel 8086 CPU计算机微处理器指令集架构)系统.不过既然Android也是基于Linux内核的系统,那么基本的启动过程也应该符合Linux的规则.下图基本描述了当你按下电源开关后Android设备的执行步骤: 一个完整的Linux系

android init进程分析 基本流程

(懒人最近想起我还有csdn好久没打理了,这个android init躺在我的草稿箱中快5年了,稍微改改发出来吧) android设备上电,引导程序引导进入boot(通常是uboot),加载initramfs.kernel镜像,启动kernel后,进入用户态程序.第一个用户空间程序是init, PID固定是1.在android系统上,init的代码位于/system/core/init下,基本功能有: 管理设备 解析并处理启动脚本init.rc 实时维护这个init.rc中的服务 init进程的

Android Init进程命令的执行和服务的启动

这里开始分析init进程中配置文件的解析,在配置文件中的命令的执行和服务的启动. 首先init是一个可执行文件,它的对应的Makfile是init/Android.mk. Android.mk定义了init程序在编译的时候,使用了哪些源码,以及生成方式.当init程序生成之后,最终会放到/init,即根目录的init文件.通常所说的init进程就是执行这个init程序. 执行这个init程序的代码是在KERNEL/init/main.c文件中的kernel_init()函数里,当kernel把一

Android init进程——解析配置文件

目录 目录 init解析配置文件 关键字定义 kw_is 解析 K_import K_on command执行 K_service service service结构体 parse_service parse_line_service init控制service init解析配置文件 在解析service服务是如何启动之前,让我们先来学习一下init进程是如何解析init.rc等配置文件的. init进程解析配置文件的代码如下(/system/core/init/init.c&&/syst

ANDROID init进程

init简要 init是Android上启动的第一个用户态进程. 执行序列是: start_kernel() -> rest_init() -> kernel_init() -> init_post() -> run_init_process() if (ramdisk_execute_command) { //rdinit, default "/init" run_init_process(ramdisk_execute_command); printk(KE