linux kernel 可以支持 init ramfs/ init rd 启动,就是在linux kernel 内核初始化完毕,切换到用户空间执行的init可以放到initrd 中,在linux menuconfig 的时候配置进去就可以将initrd 编译链接进vmlinux/zImage中了。
这样,就可以省去了rootfs 了,对于调试一些问题很方便,下面首先制作一个最简单的init rd,之后介绍将busybox 编译成initrd,这样就更强大了。
1. 配置initramfs/ initrd 配置:
initramfs source file 写上ramfs 的目录就行了。
2. 创建 initramfs
在initramfs 目录中创建如下目录:
bin dev etc lib mnt proc sbin sys tmp usr var
3. 创建 init
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int cnt = 0;
while(1)
{
printf("qc test logs: Hello World from linux userspace init ! %d\n", cnt ++);
}
return 0;
}
用 s3c6410 ARM toolchain 静态编译init.c 成init 可执行文件。
$ arm-linux-gcc -o init init.c -static
4. 创建 console 的dev 设备节点,方便从串口打印调试信息。
$mknod -m 666 console c 5 1
$ mknod -m 666 null c 1 3
static int __init kernel_init(void * unused)
{
/*
* Wait until kthreadd is all set-up.
*/
wait_for_completion(&kthreadd_done);
/*
* 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();
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;
}
kernel 初始化过程中的这段代码解释了/dev/console 的用途。
这样,直接编译make zImage 就可以了,linux kernel 启动的时候会首先启动initramfs 中的init。
参考文章: