Android Init进程

来源:互联网 发布:java select数量 编辑:程序博客网 时间:2024/05/21 16:00

Android本身就是基于Linux,因此内核的启动方式也是差不多的。Bootloader,Kernel完成系统设置以后,首先会在系统文件中寻找init文件,然后启动系统的第一个进程:init进程

 

init进程 /system/core/init/init.c

init进程主要完成以下几件事情

创建系统目录,挂载文件系统

属性服务 SystemProperty 的初始化

解析init.rc脚本文件

服务处理,轮询property_set , keychord, 进程signal的事件


创建系统目录,挂载文件系统

    /* clear the umask */    umask(0); //清除屏蔽字(file mode creation mask),保证新建的目录的访问权限不受屏蔽字影响,相当于chmod 777        /* Get the basic filesystem setup we need put         * together in the initramdisk on / and then we'll         * let the rc file figure out the rest.         */    //创建了3个主目录,2个dev下的子目录,挂载了4个文件系统    mkdir("/dev", 0755);  //设备目录,所有外部设备和虚拟设备都在这个目录    mkdir("/proc", 0755); //获取系统动态信息的目录    mkdir("/sys", 0755);  //硬件设备在内核上的映射     //虚拟内存文件系统,tmpfs下的所有内容均为临时性的内容    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/socket", 0755);    //只要pty的主复合设备/dev/ptmx被打开,就会在/dev/pts下动态的创建一个新的pty设备文件    mount("devpts", "/dev/pts", "devpts", 0, NULL);    //proc可以看作是内核内部数据结构的接口,通过它我们可以获得系统的信息,同时也能够在运行时修改特定的内核参数    mount("proc", "/proc", "proc", 0, NULL);    //与proc文件系统类似,sysfs文件系统也是一个不占有任何磁盘空间的虚拟文件系统。    //它把连接在系统上的设备和总线组织成为一个分级的文件,使得它们可以在用户空间存取    mount("sysfs", "/sys", "sysfs", 0, NULL);

解析init.rc脚本,把各种Action和Service加入到执行队列

    INFO("reading config file\n");    init_parse_config_file("/init.rc"); //解析init.rc    //将early-init这个action里的Command添加到queue_list中。early-init主要目的是启动ueventd服务    //uevent(user space event)是内核向用户空间发出的一个时间通知,使应用程序能够有机会对该event做出反应。    action_for_each_trigger("early-init", action_add_queue_tail); //添加内建的action到action list和queue_list    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); //用于等待机器冷启动完毕     queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");     queue_builtin_action(keychord_init_action, "keychord_init"); //初始化组合键服务        /* 初始化console终端      * 1.如果/proc/cmdline指定了控制台终端,那么优先使用这个控制台,如果没有指定,那么将使用默认控制台终端/dev/console。     * 2.加载开机图片,参考load_565rle_image函数     */    queue_builtin_action(console_init_action, "console_init");     /* execute all the boot actions to get us started */    //导出必要的环境变量、构建根文件系统的目录结构、配置内核属性等一些和Android系统初始化化相关内容    action_for_each_trigger("init", action_add_queue_tail);         /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random           * wasn't ready immediately after wait_for_coldboot_done      */         queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");        // 初始化属性服务    queue_builtin_action(property_service_init_action, "property_service_init");    /* 初始化Init进程信号处理。通过socketpair创建一对已连接的socket,     * 将生成的两个socket设置为O_NONBLOCK模式,也就是将对socket句柄的读写操作设置为非阻塞模式      */    queue_builtin_action(signal_init_action, "signal_init");         /* Don't mount filesystems or start core system services if in charger mode. */         if (is_charger) {         action_for_each_trigger("charger", action_add_queue_tail);     } else {         action_for_each_trigger("late-init", action_add_queue_tail);      }         /* run all property triggers based on current state of the properties */    /* 根据init.rc中action指定的property值与属性中的值比较,如果相等则执行对应的command。例如     * on property:ro.secure=0//     *  start console     * 如果当前ro.secure的值为0,那么启动console服务      */     queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); #if BOOTCHART        /* Bootchart 能够对系统的性能进行分析,并生成系统启动过程的图表,以便为你提供有价值的参考信息。     * 综合所得的信息,你就可以进行相应的改进,从而加快你的 Linux 系统启动过程。      */    queue_builtin_action(bootchart_init_action, "bootchart_init"); #endif


属性服务 SystemProperty 的初始化

/* 初始化属性服务。 * 创建/dev/__properties__ ,调用mmap映射到大小为pa_size(128*1024)共享内存。 * fd和映射地址,size都存放在结构体workspace */property_init();   INFO("property init\n");property_load_boot_defaults(); //从/default.prop设置一些默认的系统属性/* 初始化属性服务 * 1.读取/system/build.prop,/system/default.prop, /data/local.prop以及/data/property/下的属性并将其设置; * 2.创建一个服务器端UNIX Domain Socket,它的socket文件路径为/dev/socket/property_service,这个socket监听来自客户端的属性修改请求.  */queue_builtin_action(property_service_init_action, "property_service_init"); 

其他初始化工作

uevent,watchdog的入口函数

    if (!strcmp(basename(argv[0]), "ueventd")) //根据main函数的参数argv[0]判断是否启动ueventd守护进程return ueventd_main(argc, argv);       //ueventd_main将解析ueventd.rc文件,并创建相应的设备结点    if (!strcmp(basename(argv[0]), "watchdogd")) //watchdogd守护进程入口        return watchdogd_main(argc, argv);       //设备节点/dev/watchdog,设置喂狗和超时时间,循环写入""


屏蔽标准输入输出,初始化kernel log系统

    open_devnull_stdio(); //重定向stdin(0),stdout(1),stderr(2) 到 /dev/__null__ ,达到屏蔽标准输入输出的目的    klog_init();          //初始化内核log系统,内核printk的log均被写入到/dev/__kmsg__


获取硬件信息,处理kernel命令行参数,SELinux初始化

    get_hardware_name(hardware, &revision); //从proc/cpuinfo读取硬件相关信息    process_kernel_cmdline();  //解析处理bl传到kernel的命令行参数,保存在系统属性中    //SELinux 初始化,恢复SELinux文件属性    union selinux_callback cb;    cb.func_log = log_callback;    selinux_set_callback(SELINUX_CB_LOG, cb);    cb.func_audit = audit_callback;    selinux_set_callback(SELINUX_CB_AUDIT, cb);    selinux_initialize();    /* These directories were necessarily created before initial policy load     * and therefore need their security context restored to the proper value.     * This must happen before /dev is populated by ueventd.     */    restorecon("/dev");    restorecon("/dev/socket");    restorecon("/dev/__properties__");    restorecon_recursive("/sys");

服务处理,轮询property_set , keychord, 进程signal的事件

上述初始化工作都准备好了的话,就到了服务处理阶段了,这是一个死循环,主要工作就是:

1. 将init.rc及内建的actions命令,一条一条执行

2. 负责对service的管理。

3. 对signal及进程退出的处理

4. 响应property设置的请求(设置都在init中统一设置,读取进程可以自己读共享内存)

for(;;) {        int nr, i, timeout = -1;        execute_one_command(); //执行一条命令        restart_processes();   //重新启动异常退出的Service。通过遍历service_list列表,找到flags设置为         //需要重启的Service,调用restart_service_if_needed函数启动它//注册属性设置property_set_fd,监听来自属性服务property service的事件。属性服务是init提供的重要功能        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;        }//注册信号signal处理signal_recv_fd,主要用于接收子进程异常退出后内核抛出的SIGCHLD信号,//然后决定回收子进程资源或者重启子进程,防止子进程成为僵尸进程。        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;        }//注册keychord keychord_fd        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;        }// 如果有正要处理的Action,则设置timeout=0,即poll不阻塞        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//将ufds传入poll函数,监控事件的发生        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(); //收到属性设置的socket请求之后,设置相关属性。                else if (ufds[i].fd == get_keychord_fd())                    handle_keychord();                else if (ufds[i].fd == get_signal_fd())                    handle_signal(); //当有子进程终止时,也就是service终止时,内核会给init发送SIGCHLD,此时调用注册的handler函数     //这个handler函数是向其中的一个socket signal_fd写入数据,由于signal_init过程中初始化了一对     //已连接的socket signal_fd和signal_recv_fd,因此此时signal_recv_fd会收到向signal_fd写入的数据     //然后查询那个service终止,然后根据该service的属性来作相关的操作,是重启还是结束进行资源回收。            }        }    }


本文参考资料有如下:

android的init过程分析

Android的init过程详解(一)

android init进程分析 基本流程

Android系统初始化过程分析(Android 4.3)

基于android2.3.5系统:开天辟地Android启动机制[一]

3.3 init进程的执行过程(1)


0 0
原创粉丝点击