Android的property机制

来源:互联网 发布:广州数据恢复 编辑:程序博客网 时间:2024/05/21 07:56

    android 1号进程进程init进程在开机的时候就会调用property_init函数,至于init是怎么起来的,这里不是重点,所以暂时先不介绍,property_init的具体flow如下:

system/core/init/init.c

void property_init(void){    init_property_area();      }
system/core/init/property_service.c

static int init_property_area(void){    if (property_area_inited)        return -1;    if(__system_property_area_init())        return -1;    if(init_workspace(&pa_workspace, 0))        return -1;    fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC);    property_area_inited = 1;    return 0;}
bionic/libc/bionic/system_properties.c

int __system_property_area_init(){      return map_prop_area_rw();}
static int map_prop_area_rw(){    prop_area *pa;    int fd;    int ret;    /* dev is a tmpfs that we can use to carve a shared workspace     * out of, so let's do that...     */    fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC |            O_EXCL, 0444);    if (fd < 0) {        if (errno == EACCES) {            /* for consistency with the case where the process has already             * mapped the page in and segfaults when trying to write to it             */            abort();        }        return -1;    }    ret = fcntl(fd, F_SETFD, FD_CLOEXEC);    if (ret < 0)        goto out;    if (ftruncate(fd, PA_SIZE) < 0)        goto out;    pa_size = PA_SIZE;    pa_data_size = pa_size - sizeof(prop_area);    compat_mode = false;    pa = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);    if(pa == MAP_FAILED)        goto out;    memset(pa, 0, pa_size);    pa->magic = PROP_AREA_MAGIC;    pa->version = PROP_AREA_VERSION;    /* reserve root node */    pa->bytes_used = sizeof(prop_bt);    /* plug into the lib property services */    __system_property_area__ = pa;    close(fd);    return 0;out:    close(fd);    return -1;}
    看到open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC |O_EXCL, 0444);和 pa = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);我们知道文件property_filename (即 /dev/__properties__)被打开,并以读写可共享的方式映射到了内存。(其他全局变量,如pa_data_size和__system_property_area__ 暂放置一边,也不细节的讲述get_fd_from_env() )。

     property_set/property_get位于libcutils.so库,任何进程若要调用这两个函数,需要链接libcutils.so。libcutils.so调用了__system_property_set和__system_Property_get函数,这两个函数位于bionic库中,生成的库文件为libc_common.so。

bionic/libc/bionic/system_properties.c

int __system_property_set(const char *key, const char *value){    int err;    prop_msg msg;    if(key == 0) return -1;    if(value == 0) value = "";    if(strlen(key) >= PROP_NAME_MAX) return -1;    if(strlen(value) >= PROP_VALUE_MAX) return -1;    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);    if(err < 0) {        return err;    }    return 0;}
static int send_prop_msg(prop_msg *msg){    struct pollfd pollfds[1];    struct sockaddr_un addr;    socklen_t alen;    size_t namelen;    int s;    int r;    int result = -1;    s = socket(AF_LOCAL, SOCK_STREAM, 0);    if(s < 0) {        return result;    }    memset(&addr, 0, sizeof(addr));    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;    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));    if(r == sizeof(prop_msg)) {        // We successfully wrote to the property server but now we        // wait for the property server to finish its work.  It        // acknowledges its completion by closing the socket so we        // poll here (on nothing), waiting for the socket to close.        // If you 'adb shell setprop foo bar' you'll see the POLLHUP        // once the socket closes.  Out of paranoia we cap our poll        // at 250 ms.        pollfds[0].fd = s;        pollfds[0].events = 0;        r = TEMP_FAILURE_RETRY(poll(pollfds, 1, 250 /* ms */));        if (r == 1 && (pollfds[0].revents & POLLHUP) != 0) {            result = 0;        } else {            // Ignore the timeout and treat it like a success anyway.            // The init process is single-threaded and its property            // service is sometimes slow to respond (perhaps it's off            // starting a child process or something) and thus this            // times out and the caller thinks it failed, even though            // it's still getting around to it.  So we fake it here,            // mostly for ctl.* properties, but we do try and wait 250            // ms so callers who do read-after-write can reliably see            // what they've written.  Most of the time.            // TODO: fix the system properties design.            result = 0;        }    }    close(s);    return result;}
    property_service.c收到这个msg后,会根据msg.name和msg.value来设置具体的property,在这路需要说明一下,如果根据name能够找到对应的prop_info信息,那么就去update对应的value值,如果找不到对应的prop_info信息,那么就去add一个prop_info。具体flow如下:

system/core/libcutils/properties.c

int property_set(const char *key, const char *value){    char sendBuf[1+PROPERTY_KEY_MAX+PROPERTY_VALUE_MAX];    char recvBuf[1];    int result = -1;    //ALOGV("PROPERTY SET [%s]: [%s]\n", key, value);    pthread_once(&gInitOnce, init);    if (gPropFd < 0)        return -1;    if (strlen(key) >= PROPERTY_KEY_MAX) return -1;    if (strlen(value) >= PROPERTY_VALUE_MAX) return -1;    memset(sendBuf, 0xdd, sizeof(sendBuf));    // placate valgrind    sendBuf[0] = (char) kSystemPropertySet;    strcpy(sendBuf+1, key);    strcpy(sendBuf+1+PROPERTY_KEY_MAX, value);    pthread_mutex_lock(&gPropertyFdLock);    if (write(gPropFd, sendBuf, sizeof(sendBuf)) != sizeof(sendBuf)) {        pthread_mutex_unlock(&gPropertyFdLock);        return -1;    }    if (read(gPropFd, recvBuf, sizeof(recvBuf)) != sizeof(recvBuf)) {        pthread_mutex_unlock(&gPropertyFdLock);        return -1;    }    pthread_mutex_unlock(&gPropertyFdLock);    if (recvBuf[0] != 1)        return -1;    return 0;}

0 0
原创粉丝点击