我们通常使用Busybox来构建根文件系统的必要的应用程序。Busybox通过传入的参数来决定执行何种操作。当init进程启动时,实际上调用的是Busybox的init_main()函数,下面我们来分析这个函数,看init进程究竟是怎样一个流程。我分析的Busybox源码是1.7.0版本的,其他版本会略有不同。部分代码省略我们只看关键性代码。

首先看init_main函数

[cpp] view
plain
?
  1. 01.int init_main(int argc, char **argv);
  2. 02.int init_main(int argc, char **argv)
  3. 03.{
  4. 04.    ……………………………..
  5. 05.    ……………………………..
  6. 06.    //初始化控制台
  7. 07.    console_init();
  8. 08.    ………………………………
  9. 09.
  10. 10.    if (argc > 1
  11. 11.     && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1'))
  12. 12.    ) {
  13. 13.        new_init_action(RESPAWN, bb_default_login_shell, "");
  14. 14.    } else {
  15. 15.        //因为我们启动的init进程没有任何参数,所有argc==1,执行的是这一句
  16. 16.        parse_inittab();
  17. 17.    }
  18. 18.    …………………………………………
  19. 19.    …………………………………………
  20. 20.    run_actions(SYSINIT);   //运行inittab配置文件中acthion为SYSINIT的进程
  21. 21.    run_actions(WAIT);  //运行inittab配置文件中action为WAIT的进程
  22. 22.
  23. 23.
  24. 24.    run_actions(ONCE);  //运行inittba配置文件中action为ONCE的进程
  25. 25.    ………………………………………………
  26. 26.    while (1) {
  27. 27.        /*
  28. 28.        运行inittab配置文件中action为RESPAWN和ASKFIRST的进程,一旦退出则重新启动
  29. 29.        */
  30. 30.        run_actions(RESPAWN);
  31. 31.        run_actions(ASKFIRST);
  32. 32.
  33. 33.        wpid = wait(NULL);
  34. 34.        while (wpid > 0) {
  35. 35.                    a->pid = 0;
  36. 36.            }
  37. 37.            wpid = waitpid(-1, NULL, WNOHANG);
  38. 38.
  39. 39.    }
  40. 40.}

parse_inittab实际上对/etc/inittab文件里面的配置进行解释,如果没有,则设置一些默认设置。

我们先来看看这个inittab这个文件里面的配置格式,这个在busybox文件里面的inittab文件里面有说明

<id>:<runlevels>:<action>:<process>

id表示输出输入设备,这个不需要设置,因为/etc/console已经设为标准输入输出了,如不设置,则从控制台输入输出。

runlevels 这个参数完全忽略

action 运行时机,它表示inittab解释后的运行顺序,它有sysinit, respawn, askfirst, wait, once,restart, ctrlaltdel, andshutdown.这个值可选择。

process 就是要启动的进程。

下面来看prase_inittab这个函数

[cpp] view
plain
?
  1. 01.static void parse_inittab(void)
  2. 02.{
  3. 03.…………………………………………………
  4. 04.…………………………………………………
  5. 05.
  6. 06.    /*INITTAB是一个宏 #define INITTAB      "/etc/inittab"
  7. 07.    可以看得出来它打开了/etc/inittab这个文件*/
  8. 08.
  9. 09.    file = fopen(INITTAB, "r");
  10. 10.
  11. 11.    //如果没有这个文件,则调用new_init_action进行一些默认的操作
  12. 12.    if (file == NULL) {
  13. 13.        new_init_action(CTRLALTDEL, "reboot", "");
  14. 14.        new_init_action(SHUTDOWN, "umount -a -r", "");
  15. 15.        if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
  16. 16.        new_init_action(RESTART, "init", "");
  17. 17.        new_init_action(ASKFIRST, bb_default_login_shell, "");
  18. 18.        new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
  19. 19.        new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
  20. 20.        new_init_action(ASKFIRST, bb_default_login_shell, VC_4);                         new_init_action(SYSINIT, INIT_SCRIPT, "");
  21. 21.
  22. 22.        return;
  23. 23.    }
  24. 24.    …………………………………………………
  25. 25.…………………………………………………
  26. 26.        /*果inittab文件里面有内容就将里面的内容一行一行读出来,然后调用new_init_action进行操作*/
  27. 27.    while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
  28. 28.        /* Ok, now process it */
  29. 29.        for (a = actions; a->name != 0; a++) {
  30. 30.            if (strcmp(a->name, action) == 0) {
  31. 31.                if (*id != '\0') {
  32. 32.                    if (strncmp(id, "/dev/", 5) == 0)
  33. 33.                        id += 5;
  34. 34.                    strcpy(tmpConsole, "/dev/");
  35. 35.                    safe_strncpy(tmpConsole + 5, id,
  36. 36.                        sizeof(tmpConsole) - 5);
  37. 37.                    id = tmpConsole;
  38. 38.                }
  39. 39.                new_init_action(a->action, command, id);
  40. 40.                break;
  41. 41.            }
  42. 42.        }
  43. 43.    …………………………………………………
  44. 44.…………………………………………………
  45. 45.    }
  46. 46.    fclose(file);
  47. 47.}

这个new_init_action函数,它实际上是将inittab里面的action相同的操作串成一个链表。

下面我们再来分析init_main执行prase_inittab之后执行的操作

可以看出init_main执行prase_initab对inittab文件里面的配置进行解释之后,会先执行运行时机为SYSINIT的进程,让执行WAIT时机的,接着是ONCE的,然后在一个while(1)函数里面运行RESPAWN和ASKFIRST时机的,一旦这两个时机里面的进程被杀死,就会把他们的pid赋为0,然后跳到while(1)函数的开始处又去启动他们。所有说运行时机为RESPAWN和ASKFIRST的进程永远无法杀死,除非reboot或者shutdown。

 

下面我们来总结一下init进程的启动过程

1.初始化控制台

2.解释inittab

3.执行inittab运行时机为SYSINIT的进程

4.执行inittab运行时机为WAIT的进程

5.执行inittab运行时机为ONCE的进程

6.执行inittab运行时机为RESPAWN和ASKFRIST的进程,有退出的则重新执行。



ARM-Linux移植之(三)——init进程启动流程分析的更多相关文章

  1. linux根文件系统制作,busybox启动流程分析

    分析 busybox-1.1.6 启动流程,并 制作一个小的根文件系统 源码百度云链接:https://pan.baidu.com/s/1tJhwctqj4VB4IpuKCA9m1g 提取码 :l10 ...

  2. Linux内核分析-使用gdb跟踪调试内核从start_kernel到init进程启动

    姓名:江军 ID:fuchen1994 实验日期:2016.3.13 实验指导 使用实验楼的虚拟机打开shell cd LinuxKernel/ qemu -kernel linux-3.18.6/a ...

  3. 实验三:gdb跟踪调试内核从start_kernel到init进程启动

    原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 如果我写的不好或者有误的地方请留言 ...

  4. Android系统启动流程(一)解析init进程启动过程

    整体流程大致如下:     1.init简介 init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等.in ...

  5. Android系统init进程启动及init.rc全解析

    转:https://blog.csdn.net/zhonglunshun/article/details/78615980 服务启动机制system/core/init/init.c文件main函数中 ...

  6. arm linux 移植 x265

    背景 本来想着把 x265编译到ffmpeg里面,搞定了x265的编译:但是一直报ERROR: x265 not found using pkg-config这个错误,我按照网上的资料,查看了ffbu ...

  7. arm linux kernel 从入口到start_kernel 的代码分析

    参考资料: <ARM体系结构与编程> <嵌入式Linux应用开发完全手册> Linux_Memory_Address_Mapping http://www.chinaunix. ...

  8. 鸟哥的linux私房菜——第20章 启动流程、模块管理与loader

    20.1 Linux启动流程分析 Linux启动过程: 按下开机电源后计算机硬件主动读取BIOS来加载硬件信息以及硬件系统的自我测试,之后系统会主动读取第一个可启动的设备(由BIOS设置),此时就可以 ...

  9. (转)Ubuntu init启动流程分析

    原文 upstart homepage 现行的Linux distros主流的有两种init方式:一种是广为流传的System V initialization,它来源于Unix并且至今仍被各种Lin ...

随机推荐

  1. CodeForces - 767C

    花了6个小时,终于成功ac...... 两边dfs,第一遍求子树和,第二遍判断有没有2*t[s]/3和t[s]/3,因为要求的节点可能是在同一条线上,同时要有2*t[s]/3和t[s]/3的情况,且2 ...

  2. srs部署到ubuntu 18.04 server

    srs.txt ubuntu 18.04 安装 srs 1. 上传srs_40.7z和h2ws.7z到linux服务器,然后远程ssh连接 (假设登陆用户名是bob,linux服务器ip是192.16 ...

  3. java 下载文件的两种方式和java文件的上传

    一:以网络的方式下载文件 try { // path是指欲下载的文件的路径. File file = new File(path); // 以流的形式下载文件. InputStream fis = n ...

  4. LeetCode OJ:Simplify Path(简化路径)

    Given an absolute path for a file (Unix-style), simplify it. For example,path = "/home/", ...

  5. TCPL学习毕节:第六章hash表

    对于P126的哈希表构成: struct nlist *install(char *name, char *defn) { struct nlist *np; unsigned hashval; if ...

  6. js中去除两端逗号

    1.js replace(a,b)之替换字符串中所有指定字符的方法 var str = 'abcadeacf'; var str1 = str.replace('a', 'o'); alert(str ...

  7. L127

    Biggest Studies on Aspirin Show Risks Outweigh Benefits for Many People Doctors have long recommende ...

  8. 偶然遇到的samba服务器权限问题

    也许有一些参考价值. CentOS 6.4使用命令service smb start启动samba服务器,在配置文件都正确,而且对应的共享目录权限也正确,使用smbpasswd添加了用户,这之后,使用 ...

  9. 第1章 Flex介绍

    * Flex Flex 是一个高效.免费的开源框架,可用于构建具有表现力的 Web应用程序,这些应用程序利用Adobe Flash Player和Adobe AIR, 可以实现跨浏览器.桌面和操作系统 ...

  10. Android sharedUserId 使用

    在Android 系统中,所有安装到系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,.这个数字证书并不需要权威的数字证书签名机构认证,它只是用来让应用程 ...