标签:
Systemproperties类在android.os下,但这个类是隐藏的,上层程序开发无法直接使用,用Java的反射机制就可以了。int __system_property_get(const char *name, char *value) { //数据已经存储在共享内存中,通过__system_property_area__ 即可获取到,之后等待读取完返回 const prop_info *pi = __system_property_find(name); return __system_property_read(pi, 0, value);//阻塞式读取 }设置属性(客户端):
int __system_property_set(const char *key, const char *value) { msg.cmd = PROP_MSG_SETPROP; strlcpy(msg.name, key, sizeof msg.name); strlcpy(msg.value, value, sizeof msg.value); err = send_prop_msg(&msg); } //发送消息通知property_service去启动服务或者设置属性 static int send_prop_msg(prop_msg *msg) { //与/dev/socket/property_service通信 s = socket(AF_LOCAL, SOCK_STREAM, 0); connect(s, (struct sockaddr *) &addr, alen) send(s, msg, sizeof(prop_msg), 0) close(s); }可以看出读取属性比较简单,就是通过__system_property_read直接读取共享内存中的数据即可,而设置属性则是通过客户端发送socket消息让property_service去启动服务或者设置属性。
int main(int argc, char **argv) { //加入到action queue队列 queue_builtin_action(property_service_init_action, "property_service_init"); ... //将属性系统初始化函数加入action queue queue_builtin_action(property_init_action, "property_init"); ... for(;;) //执行action queue队列 //接收通过socket向property service发送的数据 nr = poll(ufds, fd_count, timeout); …… handle_property_set_fd(); } static int property_service_init_action(int nargs, char **args) { start_property_service(); } void property_changed(const char *name, const char *value) { if (property_triggers_enabled) { queue_property_triggers(name, value); drain_action_queue(); } }\system\core\init\property_service.c:
void property_init(bool load_defaults) { //初始化共享内存空间 init_property_area(); //加载属性文件 load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT); }
\bionic\libc\bionic\system_properties.c
static int init_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; /* plug into the lib property services 每个进程都会使用此变量,指向系统属性共享内存区域,访问系统属性,很重要*/ __system_property_area__ = pa; } static int init_workspace(workspace *w, size_t size) { //dev is a tmpfs是一种虚拟内存文件系统 int fd = 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__"); //保存fd size 将作为环境变量传递给每个进程 w->data = data; w->size = size; w->fd = fd; } static void load_properties_from_file(const char *fn) { //读取系统属性键值对数据写入到共享内存中 data = read_file(fn, &sz); load_properties(data); } void start_property_service(void) { //加载属性配置文件,加载的属性将覆盖原先的值。这些属性加载之后,最后加载的属性会被保持在/data/property中。 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); } void handle_property_set_fd() { //等待建立通信 s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size); //获取套接字相关信息 uid gid getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size); //接收属性设置请求消息 recv(s, &msg, sizeof(msg), 0); //处理消息 switch(msg.cmd) { case PROP_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); } void handle_control_message(const char *msg, const char *arg) { if (!strcmp(msg,"start")) { msg_start(arg); } else if (!strcmp(msg,"stop")) { msg_stop(arg); } else if (!strcmp(msg,"restart")) { msg_stop(arg); msg_start(arg); } } static void msg_start(const char *name) { service_start(svc, args); } void service_start(struct service *svc, const char *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"); } } void get_property_workspace(int *fd, int *sz) { *fd = pa_workspace.fd; *sz = pa_workspace.size; }在bionic\libc\bionic\libc_init_dynamic.c中:
//将系统属性内存空间映射到当前进程虚拟空间,进程在启动时,会加载动态库bionic libc库: void __attribute__((constructor)) __libc_preinit(void); void __libc_preinit(void) { __libc_init_common(elfdata); } void __libc_init_common(uintptr_t *elfdata) { __system_properties_init(); } int __system_properties_init(void) { prop_area *pa; int s, fd; unsigned sz; char *env; //获取环境变量ANDROID_PROPERTY_WORKSPACE //与上面init进程中设置对应 env = getenv("ANDROID_PROPERTY_WORKSPACE"); //共享内存文件描述符 内存大小 fd = atoi(env); sz = atoi(env + 1); //将文件描述符映射到当前进程虚拟空间内存,实现共享内存 pa = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0); //全局变量指向共享系统属性内存首地址 __system_property_area__ = pa; }
static int check_perms(const char *name, unsigned int uid, unsigned int gid) { //进行权限检测 for (i = 0; property_perms[i].prefix; i++) { int tmp; 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)) { return 1; } } } return 0; } property_perms[] = { { "net.rmnet0.", AID_RADIO, 0 }, { "net.gprs.", AID_RADIO, 0 }, { "net.ppp", AID_RADIO, 0 }, { "ril.", AID_RADIO, 0 }, { "gsm.", AID_RADIO, 0 }, { "persist.radio", AID_RADIO, 0 }, { "net.dns", AID_RADIO, 0 }, { "net.", AID_SYSTEM, 0 }, { "dev.", AID_SYSTEM, 0 }, { "runtime.", AID_SYSTEM, 0 }, { "hw.", AID_SYSTEM, 0 }, { "sys.", AID_SYSTEM, 0 }, { "service.", AID_SYSTEM, 0 }, { "wlan.", AID_SYSTEM, 0 }, { "dhcp.", AID_SYSTEM, 0 }, { "dhcp.", AID_DHCP, 0 }, { "vpn.", AID_SYSTEM, 0 }, { "vpn.", AID_VPN, 0 }, { "debug.", AID_SHELL, 0 }, { "log.", AID_SHELL, 0 }, { "service.adb.root", AID_SHELL, 0 }, { "persist.sys.", AID_SYSTEM, 0 }, { "persist.service.", AID_SYSTEM, 0 }, { "persist.security.", AID_SYSTEM, 0 }, { NULL, 0, 0 } }; int property_set(const char *name, const char *value) { property_changed(name, value); return 0; }以上使用到的相关的宏定义在这里:
#define PROP_SERVICE_NAME "property_service" #define PROP_PATH_RAMDISK_DEFAULT "/default.prop" #define PROP_PATH_SYSTEM_BUILD "/system/build.prop" #define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop" #define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"
还有这里 system/core/include/private/android_filesystem_config.h
#define AID_SYSTEM 1000 /* system server */ #define AID_RADIO 1001 /* telephony subsystem, RIL */ #define AID_DHCP 1014 /* dhcp client */ #define AID_VPN 1016 /* vpn system */ #define AID_SHELL 2000 /* adb and debug shell user */
代码有点长,具体来解释下这段代码都做了神马~
Init main()Android SystemProperties系统属性详解
标签:
原文地址:http://blog.csdn.net/wdong_love_cl/article/details/52404692