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子进程。

参考链接

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

原文地址:https://www.cnblogs.com/hansongjiang/p/5042999.html