bionic/libc/include/sys/system_properties.h
bionic/libc/include/sys/_system_properties.h
bionic/libc/bionic/system_properties.c
在C code中,最终调用的是Bionic中System_Properties的实现
//system_properties初始化,与server端通过mmap共享一块只读的内存,从中根据Key得到value
//如果是只读内存,那就只能实现get,不能实现set,因此set有另外一套逻辑。
int __system_properties_init(void) {
//得到环境变量ANDROID_PROPERTY_WORKSPACE
//例如我的板子上的值 ANDROID_PROPERTY_WORKSPACE=8,49152
env = getenv("ANDROID_PROPERTY_WORKSPACE");
//第一个值为fd
fd = atoi(env);
env = strchr(env, ',');
//第二个值为size
sz = atoi(env + 1);
//最后将其mmap
pa = mmap(0, sz, PROT_READ, MAP_SHARED, fd, 0);
__system_property_area__ = pa;
return 0;
}
//shared memory存储property的结构
[prop_area][toc][toc][toc]...[prop_info][prop_info][prop_info]...
//主结构,包括数量和同步信息,toc为一维数组
struct prop_area {
unsigned volatile count;
unsigned volatile serial;
unsigned magic;
unsigned version;
unsigned reserved[4];
unsigned toc[1];
};
//每个Key的结构
struct prop_info {
char name[PROP_NAME_MAX];
unsigned volatile serial;
char value[PROP_VALUE_MAX];
};
//定义最大的properties的数量为247个,实现方式:
//toc中,前8位为name也就是key的长度,后24位为prop_info位置的偏移量
/* #define PROP_MAX_ENTRIES 247 */
/* 247 -> 32620 bytes (<32768) */
#define TOC_NAME_LEN(toc) ((toc) >> 24)
#define TOC_TO_INFO(area, toc) ((prop_info*) (((char*) area) + ((toc) & 0xFFFFFF)))
//调用get命令,传入的name就是key
int __system_property_get(const char *name, char *value)
{
//根据名字找到对应的prop_info
const prop_info *pi = __system_property_find(name);
if(pi != 0) {
//从prop_info读value
return __system_property_read(pi, 0, value);
} else {
value[0] = 0;
return 0;
}
}
//根据名字找对应的prop_info
const prop_info *__system_property_find(const char *name)
{
prop_area *pa = __system_property_area__;
unsigned count = pa->count;
unsigned *toc = pa->toc;
unsigned len = strlen(name);
prop_info *pi;
while(count--) {
//遍历toc,找到和要找的key的长度相等的prop_info
unsigned entry = *toc++;
if(TOC_NAME_LEN(entry) != len) continue;
//比较,找到真正的prop_info
pi = TOC_TO_INFO(pa, entry);
if(memcmp(name, pi->name, len)) continue;
return pi;
}
return 0;
}
int __system_property_read(const prop_info *pi, char *name, char *value)
{
unsigned serial, len;
for(;;) {
serial = pi->serial;
//pi->serial是锁
while(SERIAL_DIRTY(serial)) {
__futex_wait((volatile void *)&pi->serial, serial, 0);
serial = pi->serial;
}
len = SERIAL_VALUE_LEN(serial);
memcpy(value, pi->value, len + 1);
if(serial == pi->serial) {
if(name != 0) {
strcpy(name, pi->name);
}
return len;
}
}
}
//Shared mermory只有读的权限,因此set是不走这个通道的
int __system_property_set(const char *key, const char *value)
{
memset(&msg, 0, sizeof msg);
msg.cmd = PROP_MSG_SETPROP;
strlcpy(msg.name, key, sizeof msg.name);
strlcpy(msg.value, value, sizeof msg.value);
//关键是这个实现,发送命令
err = send_prop_msg(&msg);
return 0;
}
//Set实际是通过socket发送命令,而且每调用一次都要建立连接
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
#define PROP_SERVICE_NAME "property_service"
struct prop_msg
{
unsigned cmd;
char name[PROP_NAME_MAX];
char value[PROP_VALUE_MAX];
};
static int send_prop_msg(prop_msg *msg)
{
s = socket(AF_LOCAL, SOCK_STREAM, 0);
//property_service socket name
namelen = strlen(property_service_socket);
strlcpy(addr.sun_path, property_service_socket, sizeof addr.sun_path);
addr.sun_family = AF_LOCAL;
alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1;
//Try connect
if(TEMP_FAILURE_RETRY(connect(s, (struct sockaddr *) &addr, alen) < 0)) {
close(s);
return result;
}
//发送命令
r = TEMP_FAILURE_RETRY(send(s, msg, sizeof(prop_msg), 0));
}
//可以看到,Set的命令实际是通过socket交给property_service去处理