init进程笔记

在Linux内核启动到最后时,内核会调用三个进程,PID分别为0,1,2,其中就包含了init进程(PID=1)。init进程可以说是之后所有用户进程的父进程了,它自从产生便一直存在在内存空间中直到关机。
在系统启动后,使用ps命令查看进程列表可以在最开始找到init进程,ps命令打印的是所有用户态下的进程,这是不是可以说明init进程就是一个用户进程呢?答案是否定的,init进程实际上最初是内核进程,在经过一段时间后才变为用户进程的。尽管这样,实际上init进程完成的绝大多数工作是在用户态下进行的。
init进程在内核态时,其本身实质上就是一个函数,内容如下:

static int __init kernel_init(void * unused)
{
	/*
	 * Wait until kthreadd is all set-up.
	 */
	wait_for_completion(&kthreadd_done);
	lock_kernel();

	/*
	 * init can allocate pages on any node
	 */
	set_mems_allowed(node_states[N_HIGH_MEMORY]);
	/*
	 * init can run on any cpu.
	 */
	set_cpus_allowed_ptr(current, cpu_all_mask);
	/*
	 * Tell the world that we're going to be the grim
	 * reaper of innocent orphaned children.
	 *
	 * We don't want people to have to make incorrect
	 * assumptions about where in the task array this
	 * can be found.
	 */
	init_pid_ns.child_reaper = current;

	cad_pid = task_pid(current);

	smp_prepare_cpus(setup_max_cpus);

	do_pre_smp_initcalls();
	start_boot_trace();

	smp_init();
	sched_init_smp();

	do_basic_setup();

	/* Open the /dev/console on the rootfs, this should never fail */
	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
		printk(KERN_WARNING "Warning: unable to open an initial console.\n");

	(void) sys_dup(0);
	(void) sys_dup(0);
	/*
	 * check if there is an early userspace init.  If yes, let it do all
	 * the work
	 */

	if (!ramdisk_execute_command)
		ramdisk_execute_command = "/init";

	if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
		ramdisk_execute_command = NULL;
		prepare_namespace();
	}

	/*
	 * Ok, we have completed the initial bootup, and
	 * we're essentially up and running. Get rid of the
	 * initmem segments and start the user-mode stuff..
	 */

	init_post();
	return 0;
}

分析这个函数,init进程在内核态主要完成了三件事情,其一是调用sys_open打开了控制台,同时也得到了内核的第一个文件描述符,然后进程又连续调用了两次sys_dup函数再次得到了两个文件描述符,这样系统就得到了三个文件描述符,意义分别是标准输入,标准输出,标准错误文件。之后所有的用户进程由于继承了init进程,所以最初就具有了这三个文件描述符。其二是调用prepare_namespace函数挂载根文件系统,关于根文件系统的描述(根文件系统存放位置,根文件格式)可以通过设置uboot的bootargs参数的方式给出,比如bootargs=console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3,根文件系统存放位置为第0个MMC设备的第二个分区中,根文件格式是ext3。如果挂载失败,内核会自动在5秒后进行重启。第三,内核寻找根文件系统中的init进程程序,并且执行,这个工作是在init_post函数中完成的。在init_post函数中,程序会首先尝试使用bootargs中的给出的init程序位置(/linuxrc),若发现根文件系统并未在此给出init程序,其会尝试另外四个位置寻找init程序,顺序为/sbin/init -> /etc/init -> /bin/init -> /bin/sh,如果还是未能找到init程序,系统默认启动失败。除此之外,init_post函数可以看做是init进程由内核态到用户态的过渡。
init进程过渡到用户态后,其便开始调度其他进程直到建立起我们最后看到的终端界面,调度的进程包括了login进程,命令行进程,shell进程等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值