• init进程学习


    linux的init进程

    一个在线编辑markdown文档的编辑器,是内核启动的第一个进程,init进程有很多重要的任务,它的pit
    为1,在linux shell中使用pstree命令可以看到它为其它用户进程的根.以下为某机器的pstree结果。
    
    init─┬─AliHids───9*[{AliHids}]
     ├─AliYunDun───8*[{AliYunDun}]
     ├─AliYunDunUpdate───6*[{AliYunDunUpdate}]
     ├─atd
     ├─bluetoothd
     ├─console-kit-dae───64*[{console-kit-dae}]
     ├─cron
     ├─dbus-daemon
     ├─6*[getty]
     ├─gshelld───3*[{gshelld}]
     ├─nscd───7*[{nscd}]
     ├─ntpd
     ├─polkitd───{polkitd}
     ├─rsyslogd───3*[{rsyslogd}]
     ├─sshd─┬─sshd───sftp-server
     │      └─sshd───bash───pstree
     ├─udevd───2*[udevd]
     ├─upstart-socket-
     └─upstart-udev-br
    

    android中的init进程

    *android 本身就是基于linux操作系统的,所以两者的init进程是类似的.

    init进程的主要工作

    首先大概参考下安卓/system/core/ini.c中的目录

    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;
    
        if (!strcmp(basename(argv[0]), "ueventd"))
            return ueventd_main(argc, argv);
    
        if (!strcmp(basename(argv[0]), "watchdogd"))
            return watchdogd_main(argc, argv);
    
        /* clear the umask */
        umask(0);
        //  下面的代码开始建立各种用户空间的目录,如/dev、/proc、/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);
    
            /* 检测/dev/.booting文件是否可读写和创建*/
        close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));
    
        open_devnull_stdio();
        klog_init();
        //  初始化属性
        property_init();
    
        get_hardware_name(hardware, &revision);
        //  处理内核命令行
        process_kernel_cmdline();
        … …
    
        is_charger = !strcmp(bootmode, "charger");
    
        INFO("property init
    ");
        if (!is_charger)
            property_load_boot_defaults();
    
        INFO("reading config file
    ");
        //  分析/init.rc文件的内容
        init_parse_config_file("/init.rc");
        … …//  执行初始化文件中的动作
        action_for_each_trigger("init", action_add_queue_tail);
        //  在charger模式下略过mount文件系统的工作
        if (!is_charger) {
            action_for_each_trigger("early-fs", action_add_queue_tail);
            action_for_each_trigger("fs", action_add_queue_tail);
            action_for_each_trigger("post-fs", action_add_queue_tail);
            action_for_each_trigger("post-fs-data", action_add_queue_tail);
        }
    
        queue_builtin_action(property_service_init_action, "property_service_init");
        queue_builtin_action(signal_init_action, "signal_init");
        queue_builtin_action(check_startup_action, "check_startup");
    
        if (is_charger) {
            action_for_each_trigger("charger", action_add_queue_tail);
        } else {
            action_for_each_trigger("early-boot", action_add_queue_tail);
            action_for_each_trigger("boot", 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
        //  进入无限循环,建立init的子进程(init是所有进程的父进程)
        for(;;) {
            int nr, i, timeout = -1;
            //  执行命令(子进程对应的命令)
            execute_one_command();
            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;
    //  bootchart是一个性能统计工具,用于搜集硬件和系统的信息,并将其写入磁盘,以便其
    //  他程序使用
    #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;
    }
    
    • 初始化操作
      • 22-24行的创建/dev /proc /sys 目录,具体目录结构可以参考linux目录详解
      • 26-31为挂载文件系统
      • 51行执行了解析配置文件,然后根据解析结果进行服务的启动。
    • 守护服务:84行开始进入守护服务,无限循执行init子进程。

    参考链接

    感谢以作者文章,排名不分先后

  • 相关阅读:
    linux 切换图形界面
    google浏览器插件源码目录查询
    subline注册码
    mongodb数组多值查询(条件:数据库中必须包含条件信息)
    SpringBoot多数据源解决方案(转载)
    腾讯云服务器做代理
    多线程经典问题顺序打印
    flume 1.7在windows下的安装部署与测试运行
    解决spring-boot-maven-plugin插件打包,springboot启动时报找不到主main问题
    MYSQL的B+Tree索引树高度如何计算
  • 原文地址:https://www.cnblogs.com/hansongjiang/p/5042999.html
Copyright © 2020-2023  润新知