Android4.4属性系统-初始化(上)

简介: 笔记

一、Android4.4属性系统系列文章


Android4.4属性系统-初始化

Android4.4属性系统-系统服务

Android4.4属性系统-内存空间共享

Android4.4属性系统-属性获取

Android4.4属性系统-属性设置


二、写在前面-如何阅读本系列文章


本系列文章大部分是对源码的解析和注释,所以读起来枯燥无味,并且杂乱,这是阅读系统源码无法避免的,如果你有条件,可以点击下载Android4.4源码,阅读源码可以使用eclise,AndroidStudio,vim等。

文章的章节安卓是按照代码模块区分的,例如init进程代码,libcutils代码是按章节来区分,但不同模块的代码之间是有关联的,阅读时需要经常跳转,通过搜索功能进行页内搜索即可


三、安卓属性系统介绍


Android 里有很多属性(property),每个属性都有一个名字和值,他们都是字符串格式。这些属性定义了 Android 系统的一些公共系统属性。

在Android平台中,为了让运行中的所有进程共享系统运行时所需要的各种设置值,系统开辟了属性存储区域,并提供了访问该区域的API。属性由键(key)与值(value)构成,其表现形式为“键=值”。

在访问属性值时,添加了访问权限控制,增强了访问的安全性。系统中所有运行中的进程都可以访问属性值,但仅有init进程才能修改属性值。其他进程修改属性值时,必须向init进程提出请求,最终由init进程负责修改属性值。在此过程中,init进程会先检查各属性的访问权限,而后再修改属性值。

当属性值更改后,若定义在init.rc文件中的某个特定条件得到满足,则与此条件相匹配的动作就会发生,每个动作都有一个触发器,决定动作的执行时间,记录在“on property”关键字后的命令即被执行。

3.1属性系统工作框架


8.png

从图中我们可以看出Android属性系统由有三个进程,一组属性文件和一块共享内存组成。这块共享内存保存着系统中所有的属性记录,只有Property service能写这块共享内存,并且Property service负责将属性文件中的属性记录加载到共享内存中。
  **属性读取进程**(property consumer)把这块共享内存映射到自己的进程空间,然后直接读取它。**属性设置进程**(property setter)也加载这块共享到他的进程空间,但是他不能直接写这块共享内存。当他需要增加或者修改属性的时候,通过Unix Socket发生属性给Property service,Property service将代表设置进程写入共享内存和属性文件。
Property service运行于**init进程**中。init进程首先创建一块共享内存,并把他的句柄fd存放在这块内存中,**init进程通过mmap带MAP_SHARE标志的系统调用,把这块内存映射到他的虚拟空间中,最终这块内存所有的更新将会被所有映射这块共享内存的进程看到**。共享内存句柄fd和共享内存大小存储在系统环境变量“ANDROID_PROPERTY_WORKSPACE”中,所有的进程包括属性设置进程和属性读取进程都将通过这个系统环境变量获得共享内存的句柄fd和大小,然后把这块内存映射到他们自己的虚拟空间。共享内存布局如下:

9.png


当前,属性不能被删除。也就是说一旦属性被创建,将不可以被删除,但是它们可以被修改


四、属性系统的优点


属性系统有一下四个优点

  1. 全局性:只要拥有对应的权限,就可以同步获取和修改
  2. 广泛的可访问性:在Java层,native层,shell层都可以获取和修改
  3. 初始化早:属性服务实在 init 进程中启动的
  4. 使用简单:主要就两个方法 set 和 get

但是只能支持有限的类型:string、int、long、boolean


五、属性系统的初始化和启动过程


属性服务的是从init进程中启动,init 进程(源码位于/system/core/init/init.c)主要完成:

  • 解析 init.rc 文件并执行相应动作和服务
  • 生成设备驱动节点
  • 处理子进程终止
  • 提供属性服务

先上图熟悉流程:

10.png

5.1 init进程初始化property_service

init进程是安卓系统第一个进程,由它执行系统的初始化过程,属性服务也是由它开始初始化的

system/core/init/init.h

init.h是init.c的头文件,它定义了两个重要的结构体:commandaction

#include <cutils/list.h>
struct command
{
     /* list of commands in an action */
    struct listnode clist;  //listnode结构体定义在list.h
    //command 结构体中的func指向一个函数,该函数在后续init 进程调用execute_one_command 时会被调用
    int (*func)(int nargs, char **args);
    int nargs;
    char *args[1];
};
struct action {
    /* node in list of all actions */
    struct listnode alist;
    /* node in the queue of pending actions */
    struct listnode qlist;
    /* node in list of actions for a trigger */
    struct listnode tlist;
    unsigned hash;
    const char *name;
    struct listnode commands;  //listnode结构体定义在list.h
    struct command *current;
};

system/core/init/init.c

init.c是init进程的源文件,找到入口main()函数

//引入property相关的头文件
#include <sys/system_properties.h>
#include "property_service.h"
static int property_triggers_enabled = 0;
static struct action *cur_action = NULL;
static struct command *cur_command = NULL;
static struct listnode *command_queue = NULL;
int main(int argc, char **argv)
{
    int property_set_fd_init = 0;
    //1-property初始化,位于property_service.c
    property_init();
     //2-这些目录必须在初始策略加载之前创建,因此需要将其安全上下文恢复到正确的值。这必须在由ueventd填充/dev之前发生。
     restorecon("/dev");
     restorecon("/dev/socket");
     restorecon("/dev/__properties__");
     restorecon_recursive("/sys");
     is_charger = !strcmp(bootmode, "charger");
     INFO("property init\n");
      //3-如果不是充电状态,加载默认properties
     if (!is_charger)
         property_load_boot_defaults();
    // queue_builtin_action()将 property_init_action函数放入特定的列表中
     queue_builtin_action(property_service_init_action, "property_service_init");
    /* run all property triggers based on current state of the properties */
    queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
    //进入for循环,
    for(;;) {
         int nr, i, timeout = -1;
         execute_one_command();//execute_one_command 函数从 action_queue 队列中获取 action 并执行
         restart_processes();
         if (!property_set_fd_init && get_property_set_fd() > 0) {
             ufds[fd_count].fd = get_property_set_fd();
             ufds[fd_count].events = POLLIN;
             ufds[fd_count].revents = 0;
             fd_count++;
             property_set_fd_init = 1;
         }
         if (!signal_fd_init && get_signal_fd() > 0) {
             ufds[fd_count].fd = get_signal_fd();
             ufds[fd_count].events = POLLIN;
             ufds[fd_count].revents = 0;
             fd_count++;
             signal_fd_init = 1;
         }
         if (!keychord_fd_init && get_keychord_fd() > 0) {
             ufds[fd_count].fd = get_keychord_fd();
             ufds[fd_count].events = POLLIN;
             ufds[fd_count].revents = 0;
             fd_count++;
             keychord_fd_init = 1;
         }
         if (process_needs_restart) {
             timeout = (process_needs_restart - gettime()) * 1000;
             if (timeout < 0)
                 timeout = 0;
         }
         if (!action_queue_empty() || cur_action)
             timeout = 0;
 #if BOOTCHART
         if (bootchart_count > 0) {
             if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
                 timeout = BOOTCHART_POLLING_MS;
             if (bootchart_step() < 0 || --bootchart_count == 0) {
                 bootchart_finish();
                 bootchart_count = 0;
             }
         }
 #endif
         nr = poll(ufds, fd_count, timeout);
         if (nr <= 0)
             continue;
        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }
}
//property发生改变
void property_changed(const char *name, const char *value)
{
    if (property_triggers_enabled)
        queue_property_triggers(name, value);
}
static int queue_property_triggers_action(int nargs, char **args)
{
    queue_all_property_triggers();  //位于init_parser.c
    /* enable property triggers */
    property_triggers_enabled = 1;
    return 0;
}
//从action队列中读取action并执行
void execute_one_command(void)
{   
    int ret;
    //判断是获取一个新的 action 还是继续执行 action 的 commands 列表中的下一个 command
    if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
       //对于Android属性系统,是一个新的action,cur_action==NULL,cur_command==NULL
       //从 action_queue 中 获 取 action 并 赋 值 给 cur_action,定义在init_parser.c中
       cur_action = action_remove_queue_head();  
        cur_command = NULL;
        if (!cur_action)
            return;
        INFO("processing action %p (%s)\n", cur_action, cur_action->name);
      //从 cur_action 中的 commands 节点中获取第一个 command 赋值给 cur_command
        cur_command = get_first_command(cur_action);
    } else {
        cur_command = get_next_command(cur_action, cur_command);
    }
    if (!cur_command)
        return;
    //对于 Android 属性系统,action 的 commands 节点只有一个 command,调用
   //command中 func 成员所指向的函数,此处调用 property_service_init_action函数
    ret = cur_command->func(cur_command->nargs, cur_command->args);
    INFO("command '%s' r=%d\n", cur_command->args[0], ret);
}
//从指定action结体中,获取commands链表的第一个节点
static struct command *get_first_command(struct action *act)
{
    struct listnode *node;
    node = list_head(&act->commands);
    if (!node || list_empty(&act->commands))
        return NULL;
    return node_to_item(node, struct command, clist);
}
//Android属性服务初始化函数 
static int property_service_init_action(int nargs, char **args)
{
    /* read any property files on system or data and
     * fire up the property service.  This must happen
     * after the ro.foo properties are set above so
     * that /data/local.prop cannot interfere with them.
     */
    //该方法开始读取系统中所有的property文件或者数据,并启动Property服务,但是这
  //必须在ro.foo的属性被设置之后,这样/data/local.prop就不会干扰它们
    start_property_service();  //定义在property_service.c中
    return 0;
}


目录
相关文章
|
23天前
|
人工智能 搜索推荐 物联网
Android系统版本演进与未来展望####
本文深入探讨了Android操作系统从诞生至今的发展历程,详细阐述了其关键版本迭代带来的创新特性、用户体验提升及对全球移动生态系统的影响。通过对Android历史版本的回顾与分析,本文旨在揭示其成功背后的驱动力,并展望未来Android可能的发展趋势与面临的挑战,为读者呈现一个既全面又具深度的技术视角。 ####
|
21天前
|
IDE Java 开发工具
移动应用与系统:探索Android开发之旅
在这篇文章中,我们将深入探讨Android开发的各个方面,从基础知识到高级技术。我们将通过代码示例和案例分析,帮助读者更好地理解和掌握Android开发。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和技巧。让我们一起开启Android开发的旅程吧!
|
8天前
|
监控 Java Android开发
深入探索Android系统的内存管理机制
本文旨在全面解析Android系统的内存管理机制,包括其工作原理、常见问题及其解决方案。通过对Android内存模型的深入分析,本文将帮助开发者更好地理解内存分配、回收以及优化策略,从而提高应用性能和用户体验。
|
10天前
|
存储 安全 Android开发
探索Android系统的最新安全特性
在数字时代,智能手机已成为我们生活中不可或缺的一部分。随着技术的不断进步,手机操作系统的安全性也越来越受到重视。本文将深入探讨Android系统最新的安全特性,包括其设计理念、实施方式以及对用户的影响。通过分析这些安全措施如何保护用户免受恶意软件和网络攻击的威胁,我们希望为读者提供对Android安全性的全面了解。
|
23天前
|
监控 Java Android开发
深入探讨Android系统的内存管理机制
本文将深入分析Android系统的内存管理机制,包括其内存分配、回收策略以及常见的内存泄漏问题。通过对这些方面的详细讨论,读者可以更好地理解Android系统如何高效地管理内存资源,从而提高应用程序的性能和稳定性。
56 16
|
15天前
|
安全 Android开发 iOS开发
深入探讨Android与iOS系统的差异及未来发展趋势
本文旨在深入分析Android和iOS两大移动操作系统的核心技术差异、用户体验以及各自的市场表现,进一步探讨它们在未来技术革新中可能的发展方向。通过对比两者的开放性、安全性、生态系统等方面,本文揭示了两大系统在移动设备市场中的竞争态势和潜在变革。
|
1月前
|
算法 JavaScript Android开发
|
1月前
|
安全 搜索推荐 Android开发
揭秘安卓与iOS系统的差异:技术深度对比
【10月更文挑战第27天】 本文深入探讨了安卓(Android)与iOS两大移动操作系统的技术特点和用户体验差异。通过对比两者的系统架构、应用生态、用户界面、安全性等方面,揭示了为何这两种系统能够在市场中各占一席之地,并为用户提供不同的选择。文章旨在为读者提供一个全面的视角,理解两种系统的优势与局限,从而更好地根据自己的需求做出选择。
82 2
|
1月前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。
|
1月前
|
安全 Android开发 iOS开发
深入探索iOS与Android系统的差异性及优化策略
在当今数字化时代,移动操作系统的竞争尤为激烈,其中iOS和Android作为市场上的两大巨头,各自拥有庞大的用户基础和独特的技术特点。本文旨在通过对比分析iOS与Android的核心差异,探讨各自的优势与局限,并提出针对性的优化策略,以期为用户提供更优质的使用体验和为开发者提供有价值的参考。