property_get / property_set

本文深入探讨了Android系统中用于管理系统属性的机制,包括属性的读取、设置及内部实现原理。

Andorid 4.1.2


system/core/libcutils/properties.c

int property_set(const char *key, const char *value)
{
    return __system_property_set(key, value);
}


int property_get(const char *key, char *value, const char *default_value)
{
    int len;


    len = __system_property_get(key, value);

    if(len > 0) {
        return len;
    }   
    
    if(default_value) {   // default value 为NULL, 刚不会对value 做任何改变
        len = strlen(default_value);
        memcpy(value, default_value, len + 1); 
    }   
    return len;
}


bionic/libc/bionic/system_properties.c

int __system_property_read(const prop_info *pi, char *name, char *value)
{
    unsigned serial, len;
    
    for(;;) {
        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;
        }   
    }   
}

int __system_property_get(const char *name, char *value)
{
    const prop_info *pi = __system_property_find(name);

    if(pi != 0) {
        return __system_property_read(pi, 0, value);
    } else {
        value[0] = 0;
        return 0;
    }   
}
int __system_property_set(const char *key, const char *value)
{
    int err;
    int tries = 0;
    int update_seen = 0;
    prop_msg msg;


    if(key == 0) {
        __libc_android_log_print(ANDROID_LOG_ERROR, "libc", "__system_property_set error : key = 0 \n");
        return -1;
    }
    if(value == 0) value = "";
    if(strlen(key) >= PROP_NAME_MAX) {
        __libc_android_log_print(ANDROID_LOG_ERROR, "libc", "__system_property_set error : strlen(key) >= %d, key = %s\n", PROP_NAME_MAX, key);
        return -2;
    }
    if(strlen(value) >= PROP_VALUE_MAX) {
        __libc_android_log_print(ANDROID_LOG_ERROR, "libc", "__system_property_set error : strlen(value) >= %d, value = %s \n", PROP_VALUE_MAX, value);
        return -3;
    }


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




下面对代码 `extern int __property_get_real(const char *, char *, const char *); __asm__(__USER_LABEL_PREFIX__ "property_get"); __errordecl(__property_get_too_small_error, __property_get_err_str); __BIONIC_FORTIFY_INLINE` 逐部分进行解释: ### `extern int __property_get_real(const char *, char *, const char *);` - `extern` 关键字用于声明一个函数或变量是在其他文件中定义的。这里声明了一个名为 `__property_get_real` 的函数,该函数返回一个 `int` 类型的值,并且接受三个参数,每个参数都是 `const char *` 类型,也就是指向常量字符的指针。通常,这意味着在当前文件中不会定义这个函数,而是在其他源文件中实现。 ### `__asm__(__USER_LABEL_PREFIX__ "property_get");` - `__asm__` 是 GCC 编译器中用于嵌入汇编代码的关键字。 - `__USER_LABEL_PREFIX__` 通常是一个预定义的宏,用于在汇编代码中添加合适的前缀,以符合目标平台的命名规则。 - `"property_get"` 是汇编代码中的标签名。这行代码的作用是在汇编层面定义一个名为 `property_get` 的标签,这个标签可能会被链接器或汇编器使用,用于实现函数调用或者其他汇编相关的操作。 ### `__errordecl(__property_get_too_small_error, __property_get_err_str);` - `__errordecl` 可能是一个自定义的宏,用于声明一个错误相关的信息。 - `__property_get_too_small_error` 可能是一个错误码或者错误标识符。 - `__property_get_err_str` 可能是一个字符串,用于描述 `__property_get_too_small_error` 这个错误的具体信息。这行代码的作用是声明一个错误,当 `__property_get_real` 函数执行过程中出现 `__property_get_too_small_error` 错误时,可以使用 `__property_get_err_str` 来输出错误信息。 ### `__BIONIC_FORTIFY_INLINE` - `__BIONIC_FORTIFY_INLINE` 可能是 Bionic C 库中的一个宏,用于启用某种强化功能。Bionic 是 Android 系统中使用的 C 库,`__BIONIC_FORTIFY_INLINE` 可能用于内联一些安全检查代码,以防止缓冲区溢出等安全问题。在调用 `__property_get_real` 函数时,这个宏可能会插入一些额外的代码来确保函数调用的安全性。 ### 代码示例 ```c // 假设这是一个使用上述声明的示例代码 #include <stdio.h> // 声明 __property_get_real 函数 extern int __property_get_real(const char *, char *, const char *); // 假设 __USER_LABEL_PREFIX__ 定义如下 #define __USER_LABEL_PREFIX__ "" // 假设 __errordecl 宏定义如下 #define __errordecl(error, str) printf("Error declared: %s\n", str) // 假设 __BIONIC_FORTIFY_INLINE 宏定义如下 #define __BIONIC_FORTIFY_INLINE // 模拟 __property_get_real 函数的实现 int __property_get_real(const char *key, char *value, const char *default_value) { // 简单示例,返回 0 表示成功 return 0; } int main() { const char *key = "example_key"; char value[100]; const char *default_value = "default"; // 调用 __property_get_real 函数 int result = __property_get_real(key, value, default_value); if (result == 0) { printf("Property get successful\n"); } else { printf("Property get failed\n"); } return 0; } ``` ### 相关问题 1. `__USER_LABEL_PREFIX__` 宏在不同平台上的定义有什么不同? 2. `__errordecl` 宏通常在哪些场景下使用? 3. `__BIONIC_FORTIFY_INLINE` 宏具体实现了哪些安全检查? 4. `__property_get_real` 函数的具体实现逻辑是怎样的? 5. 如何在代码中处理 `__property_get_too_small_error` 错误?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值