• i.mx6 Android5.1.1 初始化流程之init进程(未完成)


    概述:

    接在i.mx6 Android5.1.1 初始化流程之框架之后

    参考资料:http://blog.csdn.net/mr_raptor/article/category/799879

    相关源码:  /system/core/init/

    相关配置文件:/system/core/rootdir/

    从下面全文可以得出:

    1).init进程和其相关的文件init.rc、ueventd.rc是在ramdisk.img中

    2).修改节点权限:  /ueventd.rc   /ueventd.Freescale.rc

    3). 修改相关服务和创建文件:/init.rc  

    1. mian.c

    关于代码中的属性服务,可以查看:i.mx6 Android5.1.1 系统属性   

    关于代码中的init.rc,可以查看:      i.mx6 Android5.1.1 初始化流程之init.rc解析

    int main(int argc, char **argv)
    {
        int fd_count = 0;
        struct pollfd ufds[4];
        char *tmpdev;
        char* debuggable;
        char tmp[32];
        int property_set_fd_init = 0;
        int signal_fd_init = 0;
        int keychord_fd_init = 0;
        bool is_charger = false;
        char watchdog[PROPERTY_MAX_VALUE];
        int ret;
        
      /*后面两个是初始化ueventd和看门狗,从上一章的ps中可以看出,这两个确实是进程init(PID=1)最初创建的两个进程*/
      /*查看是否有看门狗的属性*/ ret
    = property_get("ro.boot.watchdogd", watchdog);
      /*启动ueventd进程*/
    if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv);    if (!strcmp(basename(argv[0]), "watchdogd")) { if(ret && !(strcmp(watchdog, "disabled"))) { return 0; } else { return watchdogd_main(argc, argv); /*在这里启动看门狗*/ } } /* clear the umask */ umask(0); /* 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. */

      /* 创建目录,挂在文件系统,给权限
       * tmpfs :/dev

       * devpts :/dev/pts
       * proc :/proc  
       * sysfs :/sys
       */ mkdir(
    "/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); open_devnull_stdio(); //将标准输入、输出、错误定向到空 klog_init();     //将log重定向到/proc/kmsg当中 property_init(); //初始化属性服务,关于属性服务,可以查看:i.mx6 Android5.1.1 系统属性 get_hardware_name(hardware, &revision); //得到硬件信息和版本信息 get_soc_name(soc); //得到soc名字 process_kernel_cmdline(); // 设置基本属性 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"); is_charger = !strcmp(bootmode, "charger"); INFO("property init "); property_load_boot_defaults(); //加载/default.prop文件 进行默认属性配置相关的工作 INFO("reading config file "); init_parse_config_file("/init.rc"); //注意:解析/init.rc,并将所有元素加入链表,关于init.rc,可以查看:i.mx6 Android5.1.1 系统属性 

      /* 首先说明一下,在函数中对于init.rc命令的解析之后,将所有命令分类分别挂在了action_list,service_list,action_queue三个链表当中
       *
    serevice_list:用于保存init.rc当中的service配置信息
       * action_list: 用于保存从init.rc当中解析出来的所有action
       * action_queue: 用于保存所有待执行的action
       *
       * 下面的两个函数action_for_each_trigger和queue_builtin_action

       * action_for_each_trigger:将action加入到action_queue当中,表示正准备执行
       * queue_builtin_action: 创建一个action,并将其挂在atcion_queue和action_list当中,
       */
        action_for_each_trigger("early-init", action_add_queue_tail); //接着上面,把链表中为on early-init的元素提取执行。(我们没有)将early-init动作添加到链表action_queue中   
        
        queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); //创建wait_for_coldboot_done动作并添加到链表action_queue和action_list中,在这里注意action_list用于保存从init.rc中解析出来的所有Action,而action_queue却是用于保存待执行的Action,action_queue是一个待执行队列。
     
        queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
        queue_builtin_action(keychord_init_action, "keychord_init");
        queue_builtin_action(console_init_action, "console_init");
    
        /* execute all the boot actions to get us started */
        action_for_each_trigger("init", action_add_queue_tail);//执行Init.rc中的on init(这个我们就有了),后面分析
    
        /* 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");
        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 */
        queue_builtin_action(queue_property_triggers_action, "queue_property_triggers");
    
    
    #if BOOTCHART
        queue_builtin_action(bootchart_init_action, "bootchart_init");
    #endif
      
        for(;;) {
            int nr, i, timeout = -1;
    
            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(); } } } return 0; }

    小结:

    1。启动ueventd和watchdogd进程

    2。将标准输入,输出,错误定向到null

    3.重定向log

    4.初始化属性的区域

    5.添加各种属性

    6.解析init.rc

    7.将init.rc中解析出来的行为进行分类保存,并再添加一些默认行为

    8.进入循环守护

      1). 执行action_queue中的action

      2). 守护一些关键进程

      3). 建立属性、信号、组合按键的监听。当有行为发生时,对其进行相应处理,没有则停滞在这里 

    从上诉程序可以分析出action的执行顺序为:

    early-init                   ------------------>>init.rc
    wait_for_coldboot_done
    mix_hwrng_into_linux_rng
    keychord_init
    console_init
    init         ------------------>>init.rc
    mix_hwrng_into_linux_rng
    property_service_init
    signal_init
    charger或者late-init  ------------------>>init.rc
    queue_property_triggers

    2. ueventd_main

    int ueventd_main(int argc, char **argv)
    {
        struct pollfd ufd;
        int nr;
        char tmp[32];
    
        /*
         * init sets the umask to 077 for forked processes. We need to
         * create files with exact permissions, without modification by
         * the umask.
         */
        umask(000);
    
        /* Prevent fire-and-forget children from becoming zombies.
         * If we should need to wait() for some children in the future
         * (as opposed to none right now), double-forking here instead
         * of ignoring SIGCHLD may be the better solution.
         */
        signal(SIGCHLD, SIG_IGN);
    
        open_devnull_stdio();
        klog_init();
    #if LOG_UEVENTS
        /* Ensure we're at a logging level that will show the events */
        if (klog_get_level() < KLOG_INFO_LEVEL) {
            klog_set_level(KLOG_INFO_LEVEL);
        }
    #endif
    
        union selinux_callback cb;
        cb.func_log = log_callback;
        selinux_set_callback(SELINUX_CB_LOG, cb);
    
        INFO("starting ueventd
    ");
    
        /* Respect hardware passed in through the kernel cmd line. Here we will look
         * for androidboot.hardware param in kernel cmdline, and save its value in
         * hardware[]. */
        import_kernel_cmdline(0, import_kernel_nv);
    
        get_hardware_name(hardware, &revision);
        //解析ueventd.rc和ueventd.fressale.rc
        ueventd_parse_config_file("/ueventd.rc");
    
        snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
        ueventd_parse_config_file(tmp);
        //设备初始化
        device_init();
    
        ufd.events = POLLIN;
        ufd.fd = get_device_fd();
    
        while(1) {
            ufd.revents = 0;
            nr = poll(&ufd, 1, -1);    //循环等待
            if (nr <= 0)
                continue;
            if (ufd.revents & POLLIN)
                   handle_device_fd();  //讲接收过来的信息进行处理
        }
    }

    往下查看 i.mx6 Android5.1.1 初始化流程之init.rc解析

  • 相关阅读:
    第三周学习进度条
    绘制echarts折线图
    第二周学习进度条
    返回一个整数数组中最大子数组的和
    软件工程第二周开课博客
    第一周学习进度条
    学习进度
    学习进度
    学习进度
    HDU 4906 (dp胡乱搞)
  • 原文地址:https://www.cnblogs.com/maogefff/p/7655330.html
Copyright © 2020-2023  润新知