07.构建根文件系统之init进程分析
  根文件系统有许多命令,比如 ls cp,cd,这些命令其实也就是相当于一个应用程序。这些程序都封装在busybox中。编译busybox后就可以得到busybox,ls等命令就是到busybox的链接,执行ls等命令其实执行的是busybox程序。
   busybox应用程序中,ls对应的是ls.c,cp对应的是cp.c。ubbot目的是启动内核,内核的目的是启动应用程序。内核如何启动应用程序呢?内核启动的第一个是init进程。不同的设备有不同的驱动程序,init如何区分呢?下面我们分析程序。
init.c
	/* Check if we are supposed to be in single user mode */
	/*linux内核启动应用程序的时候并没有给他什么参数,所以argc = 1*/
	if (argc > 1
	 && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1'))
	) {
		/* Start a shell on console */
		new_init_action(RESPAWN, bb_default_login_shell, "");
	} else {
		/* Not in single user mode -- see what inittab says */
		/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
		 * then parse_inittab() simply adds in some default
		 * actions(i.e., runs INIT_SCRIPT and then starts a pair
		 * of "askfirst" shells */
		parse_inittab();
	}
static void parse_inittab(void)
{
#if ENABLE_FEATURE_USE_INITTAB
	FILE *file;
	char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
	char tmpConsole[CONSOLE_NAME_SIZE];
	char *id, *runlev, *action, *command, *eol;
	const struct init_action_type *a = actions;
	/*打开配置文件*/
	/*inittab格式
	<id>:<runlevels>:<action>:<process>
	id => /dev/id,用作中断:stdin,stdout,stderr:printf,scanf,err
	runlevels:忽略
	<action>: Valid actions include: sysinit, respawn, askfirst, wait, once,
	                                 restart, ctrlaltdel, and shutdown.
	action:指示何时执行
	process:应用程序或者脚本
	*/
	file = fopen(INITTAB, "r");
	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, "");
		/*static void new_init_action(int action,const char -cmmand,const *cons)*/
		/*new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2");*/
		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;
/*new_init_action*/
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);
		
/*结构体*/
struct init_action {
	struct init_action *next;
	int action;
	pid_t pid;
	char command[INIT_BUFFS_SIZE];
	char terminal[CONSOLE_NAME_SIZE];
/*从默认的new_init_action反推出默认的配置文件*/
/*
inittab格式
	<id>:<runlevels>:<action>:<process>
	id => /dev/id,用作中断:stdin,stdout,stderr:printf,scanf,err
	runlevels:忽略
	<action>: Valid actions include: sysinit, respawn, askfirst, wait, once,
	                                 restart, ctrlaltdel, and shutdown.
	action:指示何时执行
	process:应用程序或者脚本
*/
		/* Reboot on Ctrl-Alt-Del */
		/*::CTRLALTDEL:reboot*/
		new_init_action(CTRLALTDEL, "reboot", "");
		/* Umount all filesystems on halt/reboot */
		/*::SHUTDOWN:umount -a -r*/
		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 */
		/*::RESTART:init*/
		new_init_action(RESTART, "init", "");
		/* Askfirst shell on tty1-4 */
		/*new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2");*/
		/*::ASKFIRST:-/bin/sh*/
		/*tty2::ASKFIRST:-/bin/sh*/
		/*tty3::ASKFIRST:-/bin/sh*/
		/*tty4::ASKFIRST:-/bin/sh*/
		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, "");
/**/
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);
				}
			}
		}
	}
}
};
/*信号量*/
/*当我们按下ctrlaltdel,内核会给init进程发一个信号。接收到信号后,会执行ctrlaltdel_signal*/
signal(SIGINT, ctrlaltdel_signal);
/**/
static void ctrlaltdel_signal(int sig ATTRIBUTE_UNUSED)
{
	run_actions(CTRLALTDEL);//执行这一类的应用程序
}
  
 - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
init进程流程以及涉及的项
 busybox ->init_main
   parse_inittab
     file = fopen(INITTAB, “r”);
       new_init_action //创建一个结构体,填充
              //把这个结构放入init_action_list链表
 run_actions(SYSINIT);
   waitfor(a, 0);//等待执行完毕应用程序
      run(a)//创建process子进程
      waitpid()runpid,&status,0);//等待结束
    delete_init_action(a);//在init_action_list链表中删除应用程序
 run_actions(WAIT);
   waitfor(a, 0);//等待执行完毕应用程序
      run(a)//创建process子进程
      waitpid()runpid,&status,0);//等待结束
    delete_init_action(a);//在init_action_list链表中删除应用程序
 run_actions(ONCE);
      run(a)//创建process子进程
       delete_init_action(a);//在init_action_list链表中删除应用程序
 while (1) {
    run_actions(RESPAWN);//重新退出运行子进程
      if (a->pid == 0) {
       a->pid = run(a);
       }
    run_actions(ASKFIRST);
      if (a->pid == 0) {
       a->pid = run(a);
          "\nPlease press Enter to activate this console. ";
         while (read(0, &c, 1) == 1 && c != ‘\n’)//等待回车
         创建进程
       }
    wpid = wait(NULL);//等待子进程退出
    while (wpid > 0) {
 a->pid = 0;//退出后,就设置pid为0
 }
 }
 最小的根文件系统需要的项:
   /dev/console /dev/null
   init程序,即busybox
   /etc/inittab
   配置文件指定的应用程序
   库(某些函数的C库)
文章来源: blog.csdn.net,作者:嵌入式与Linux那些事,版权归原作者所有,如需转载,请联系作者。
原文链接:blog.csdn.net/qq_16933601/article/details/102942848
- 点赞
- 收藏
- 关注作者
 
             
           
评论(0)