我们通常使用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. linux rpm 卸载,简单说明

    平时Linux卸载文件总是遇到卸载不干净,各种依赖什么的,今天又是搞这玩意,就记录下一个比较常规的方法. 一.查询包括某关键字的软件(这里以卸载openoffice为例) 查询包括office的软件 ...

  2. 交换机上的trunk,hybrid,access配置和应用(转)

    交换机上的trunk,hybrid,access配置和应用 以太网端口的链路类型: Access类型:端口只能属于一个vlan,一般用于连接计算机. Trunk类型:端口可以属于端个vlan,可以接收 ...

  3. 解析session与cookie

    Session和Cookie相关概念 Session和Cookie都是有服务器生成的. Session和Cookie都是键值对形式保存,主要用于存储特定的一些状态值. Session保存在服务器,Co ...

  4. idea结合git使用(正常项目开发过程中的使用)

    1.如何将本地项目代码提交到公司码云上面 1.项目右键 2. 在远处的remotes里面设置你的url

  5. Redis 命令,键(key),字符串(String),哈希(Hash),列表(List),集合(Set)(二)

      Redis 命令 Redis 命令用于在 redis 服务上执行操作. 要在 redis 服务上执行命令需要一个 redis 客户端.Redis 客户端在我们之前下载的的 redis 的安装包中. ...

  6. LeetCode OJ:Jump Game(跳跃游戏)

    Given an array of non-negative integers, you are initially positioned at the first index of the arra ...

  7. UI- Layer的使用总结(附动画)

    #pargma mark - Layer 1. 设置当前视图的背景颜色 self.view.backgroundColor = [UIColor lightGrayColor]; 2. 创建一个视图, ...

  8. H264提供了哪些帧内预测?

    H.264/AVC 提供了四种帧内预测方式:4x4 亮度块的帧内预测(Intra_4x4).16x16 亮度块的帧内预测(Intra_16x16).8x8 色度块的帧内预测(Intra_chroma) ...

  9. C++纯虚函数实现

    纯虚函数就是一个在基类中的虚函数,差别只是在一般的虚函数声明的后面加了"=0",虚函数允许函数通过与函数体之间的联系在运行时才建立,也就是在运行时才决定如何动作,称为运行时的多态性 ...

  10. 前端之jQuery02

    文档操作 重点:创建标签,jQuery里面没有这个方法 内部(子标签) 添加到指定元素内部后面 $(A).append(B): // B作为A的最后一个儿子元素:(把B追加到A) $(A).appen ...