前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >07.构建根文件系统之init进程分析

07.构建根文件系统之init进程分析

作者头像
嵌入式与Linux那些事
发布2021-05-20 15:05:19
9210
发布2021-05-20 15:05:19
举报

  根文件系统有许多命令,比如 ls cp,cd,这些命令其实也就是相当于一个应用程序。这些程序都封装在busybox中。编译busybox后就可以得到busybox,ls等命令就是到busybox的链接,执行ls等命令其实执行的是busybox程序。   busybox应用程序中,ls对应的是ls.c,cp对应的是cp.c。ubbot目的是启动内核,内核的目的是启动应用程序。内核如何启动应用程序呢?内核启动的第一个是init进程。不同的设备有不同的驱动程序,init如何区分呢?下面我们分析程序。

init.c

代码语言:javascript
复制
	/* 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);//执行这一类的应用程序
}

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库)

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档