android properties分析(3) Bionic code properties设置和获取的接口分析

来源:互联网 发布:智能降温的软件 编辑:程序博客网 时间:2024/06/05 02:00

Bionic code properties设置和获取的接口:

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去处理

原创粉丝点击