当前位置: 代码迷 >> 综合 >> 4.2【根文件系统】init进程分析
  详细解决方案

4.2【根文件系统】init进程分析

热度:48   发布时间:2023-10-15 00:19:35.0

一、busybox:ls,cp等命令的组合

    执行:ls  "/sbin/init 会发现/sbin/init-->../bin/busybox

    所以"/sbin/init"也是在busybox进程中,所以要分析这些,需要进入busybox中分析

二、uboot启动内核,内核启动应用程序

    内核----->../sbit/init/----->应用程序

 

    int程序:1、配置文件---->2、解析配置文件---->3、执行应用程序

                        配置文件:指定程序-->指定执行时间

三、阅读源码

    解压缩:busybox-1.7.0.tar.bz2

 

   1、 init.c (位于busybox-1.7.0\init)

        busybox--->init_main,

                init_main--->parse_inittab();

                    #define INITTAB      "/etc/inittab"

                    parse_inittab--->file = fopen(INITTAB, "r");//打开配置文件/etc/inittab   

                        new_init_action

                            run_actions(SYSINIT);

                            run_actions(WAIT);

                            run_actions(ONCE);

                            while (1) {

                                run_actions(RESPAWN);

                                run_actions(ASKFIRST);

                                sleep(1);

                                }

inittab格式:

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

inittab文件下部分说明(busybox-1.7.0\examples)

# <id>:The contents of this field are appended to "/dev/" and used as-is.

      id=>/dev/id.用作终端:stdin、stdout、stderr 、printf、scanf、err

# <runlevels>: The runlevels field is completely ignored.

      runlevels完全可以忽略掉

# <action>: Valid actions include: sysinit, respawn, askfirst, wait, once,   restart, ctrlaltdel, and shutdown.

     action指定何时执行

# <process>: Specifies the process to be executed and it's command line.

     process:应用程序或者脚本

 

    如果没有配置文件,将执行默认的配置,即if下面的代码    

if (file == NULL) {/* No inittab file -- set up some default behavior */#endif/* Reboot on Ctrl-Alt-Del */new_init_action(CTRLALTDEL, "reboot", "");/* Umount all filesystems on halt/reboot */new_init_action(SHUTDOWN, "umount -a -r", "");/* Swapoff on halt/reboot */if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");/* Prepare to restart init when a HUP is received */new_init_action(RESTART, "init", "");/* Askfirst shell on tty1-4 */new_init_action(ASKFIRST, bb_default_login_shell, "");new_init_action(ASKFIRST, bb_default_login_shell, VC_2);new_init_action(ASKFIRST, bb_default_login_shell, VC_3);new_init_action(ASKFIRST, bb_default_login_shell, VC_4);/* sysinit */new_init_action(SYSINIT, INIT_SCRIPT, "");return;#if ENABLE_FEATURE_USE_INITTAB}

如果有的话将执行下面的方法,对配置文件解析

while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {/* Skip leading spaces */for (id = buf; *id == ' ' || *id == '\t'; id++);/* Skip the line if it's a comment */if (*id == '#' || *id == '\n')  //如果是#或者\n就忽略掉continue;/* Trim the trailing \n *///XXX: chomp() ?eol = strrchr(id, '\n');if (eol != NULL)*eol = '\0';/* Keep a copy around for posterity's sake (and error msgs) */strcpy(lineAsRead, buf);/* Separate the ID field from the runlevels */runlev = strchr(id, ':');if (runlev == NULL || *(runlev + 1) == '\0') {message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);continue;} else {*runlev = '\0';++runlev;}/* Separate the runlevels from the action */action = strchr(runlev, ':');if (action == NULL || *(action + 1) == '\0') {message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);continue;} else {*action = '\0';++action;}/* Separate the action from the command */command = strchr(action, ':');if (command == NULL || *(command + 1) == '\0') {message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);continue;} else {*command = '\0';++command;}/* Ok, now process it */for (a = actions; a->name != 0; a++) {if (strcmp(a->name, action) == 0) {if (*id != '\0') {if (strncmp(id, "/dev/", 5) == 0)  //将id加上/dev/前缀id += 5;strcpy(tmpConsole, "/dev/");safe_strncpy(tmpConsole + 5, id,sizeof(tmpConsole) - 5);id = tmpConsole;}new_init_action(a->action, command, id);  //解析完后执行new_init_actionbreak;}}if (a->name == 0) {/* Choke on an unknown action */message(L_LOG | L_CONSOLE, "Bad inittab entry: %s", lineAsRead);}}

 

        分析 new_init_action(ASKFIRST, bb_default_login_shell, VC_2);

new_init_action(ASKFIRST, bb_default_login_shell, VC_2);# define VC_2 "/dev/tty2"#define LIBBB_DEFAULT_LOGIN_SHELL      "-/bin/sh"new_init_action(ASKFIRST, "-/bin/sh","/dev/tty2");static void new_init_action(int action, const char *command, const char *cons){struct init_action *new_action, *a, *last;if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))return;/* Append to the end of the list */for (a = last = init_action_list; a; a = a->next) {/* don't enter action if it's already in the list,* but do overwrite existing actions */if ((strcmp(a->command, command) == 0)&& (strcmp(a->terminal, cons) == 0)) {a->action = action;return;}last = a;}new_action = xzalloc(sizeof(struct init_action));if (last) {last->next = new_action;} else {init_action_list = new_action;}strcpy(new_action->command, command);new_action->action = action;strcpy(new_action->terminal, cons);messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",new_action->command, new_action->action, new_action->terminal);}

 

    总结:

第一步:new_init_action创建一个init_action结构,填充

第二步:把new_init_action放入init_action_list链表


 

static void run_actions(int action){struct init_action *a, *tmp;for (a = init_action_list; a; a = tmp) {tmp = a->next;if (a->action == action) {/* a->terminal of "" means "init's console" */if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {delete_init_action(a);} else if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {waitfor(a, 0);delete_init_action(a);} else if (a->action & ONCE) {run(a);delete_init_action(a);} else if (a->action & (RESPAWN | ASKFIRST)) {/* Only run stuff with pid==0.  If they have* a pid, that means it is still running */if (a->pid == 0) {a->pid = run(a);}}}}}

waitfor(a, 0);   ---->执行应用程序,等待程序执行完毕

        run(a)--->创建process子进程

            waitpid(runpid, &status, 0); --->等待结束

static int waitfor(const struct init_action *a, pid_t pid){int runpid;int status, wpid;runpid = (NULL == a)? pid : run(a);while (1) {wpid = waitpid(runpid, &status, 0);if (wpid == runpid)break;if (wpid == -1 && errno == ECHILD) {/* we missed its termination */break;}/* FIXME other errors should maybe trigger an error, but allow* the program to continue */}return wpid;}

delete_init_action(a);  ---->在init_action_list链表中删除

 

 

 

init的步骤

第一步:配置文件

    配置文件:/dev/console  --->  /dev/null  ----> /etc/initab  --->  配置文件里指定的应用程序  ---> C库

init本身即busybox

 

四、编译busybox

        1、解压:jar xjf busybox-1.7.0.tar.bz2

        2、打开busybox-1.7.0文件夹下的INSTALL文件,可以看到一些编译的教程

Building:

=========

The BusyBox build process is similar to the Linux kernel build:

 

  make menuconfig     # This creates a file called ".config"

  make                # This creates the "busybox" executable

  make install        # or make CONFIG_PREFIX=/path/from/root install

 

The full list of configuration and install options is available by typing:

 

  make help

          3、执行make menuconfig生成配置文件

                因为是给Linux开发板编译的,所以需要用到交叉编译工具

                    打开Makefile,搜索CROSS,定位到下面代码并进行更改

原代码

ARCH        ?= $(SUBARCH)

CROSS_COMPILE    ?=

更改后

ARCH        ?= $(SUBARCH)

CROSS_COMPILE    ?=arm-linux-

           

        4、配置完成后执行make  

        5、make完成后,千万不要使用make install ,它会加载到PC上去,破坏PC

                创建一个文件夹:mkdir -p /work/nfs_root/first_fs

                安装到这个文件夹里面:  make CONFIG_PREFIX=/work/nfs_root/first_fs install

        6、跳转到/work/nfs_root/first_fs查看:cd /work/nfs_root/first_fs

                                                                      ls -l

            

  相关解决方案