码迷,mamicode.com
首页 > 其他好文 > 详细

OpenWRT新框架的boot过程

时间:2014-07-17 18:14:30      阅读:1080      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   strong   

昨天在分析procd如何工作的时候,有找到过下面这样一段描述新架构boot过程的文字:

1) Bootloader (uboot, redboot, adam2, grub, …)
2) Linux kernel starts, tries to find the mtd partition called “rootfs”, mounts it
3) Linux executes /etc/preinit
4) Preinit waits a few seconds for failsafe triggering
5) Preinit mounts or initializes the jffs2 overlay
6) Preinit loads kernel modules specified in /etc/modules.d/
7) Preinit executes hotplug2, a kernel uevent handler
8) Preinit hands control off to init to start the main boot
9) The init process executes all /etc/rc.d/ scripts to bring up services

今天发现,事实并不是这样的,至少在我手上的系统中并非如此。首先,我在uboot中打印了uboot传给kernel的参数(著名的cmdline参数):

bootargs=console=ttyS0,115200 root=31:02 rootfstype=squashfs init=/sbin/init mtdparts=ar7240)
bootcmd=bootm 0x9F020000

其中,root=31:02是告诉kernel知道rootfs是在mtdblock2上面。使用这种挂载rootfs的方式时,kernel必须包含有加载rootfs所需要的全部驱动,即,这里的kernel在编译时是加入了mtd设备相关驱动程式的。

kernel在挂载完rootfs之后,根据uboot告诉它的init=path_to_init_file参数,kernel会找到path_to_init_file并执行这个文件。

所以,这里,我们的系统在挂载文件系统之后,是先执行的/sbin/init。

init是一个用C写的程序,同样也是在luci2新框架下面。找了一下它的代码,在luci2/procd/initd/init.c,具体如下(只是main):

int
main(int argc, char **argv)
{
        pid_t pid;

        sigaction(SIGTERM, &sa_shutdown, NULL);
        sigaction(SIGUSR1, &sa_shutdown, NULL);
        sigaction(SIGUSR2, &sa_shutdown, NULL);

        early();
        cmdline();
        watchdog_init(1);

        pid = fork();
        if (!pid) {
                char *kmod[] = { "/sbin/kmodloader", "/etc/modules-boot.d/", NULL };

                if (debug < 3) {
                        int fd = open("/dev/null", O_RDWR);

                        if (fd > -1) {
                                dup2(fd, STDIN_FILENO);
                                dup2(fd, STDOUT_FILENO);
                                dup2(fd, STDERR_FILENO);
                                if (fd > STDERR_FILENO)
                                        close(fd);
                        }
                }
                execvp(kmod[0], kmod);
                ERROR("Failed to start kmodloader\n");
                exit(-1);
        }
        if (pid <= 0)
                ERROR("Failed to start kmodloader instance\n");
        else
                waitpid(pid, NULL, 0);
        uloop_init();
        preinit();
        uloop_run();

        return 0;
}

我们看到,这里其实一直到最后才进行了preinit。

不过,在此之前进行的操作都和用户没多大关系,所以,似乎直接认为是从preinit好像也没什么不妥。

唔,忍不住对main里面调用的几个函数进行了进一步挖掘。

early() 是在luci2/procd/initd/early.c中,可以在这里看到,它打印了一条消息:“Console is alive”。这条信息在启动打印信息里面是可以明显看到的。它在后台做的事情还包括了(这些是在打印Console is alive前就完成的):

1. 挂载proc,sysfs,tmpfs。

2. 添加设备/dev/null。

3. 将stdin,stdout,stderr都设置为我们指定的设备,比如“/dev/console”;如果我们没有指定设备,会被设置为/dev/nul,即被扔掉。

cmdline() 是在luci2/procd/initd/init.c中,它是从/proc/cmdline中取出init_debug,并设置debug等级。

watchdog() 就不用说了。

然后后面的,通过execvp来执行“ /sbin/kmodloader /etc/modules.d/”,则是把分离编译的kernel module设备挂载上来。

这里就到最后了,就是preinit()。这里其实也是先执行了“ /sbin/procd -h /etc/hotplug-preinit.json ”,然后才执行的“/bin/sh /etc/preinit”。具体在preinit中,则又是去执行在/lib/preinit下的一个个脚本。这里有个神奇的/lib/functions.sh,比较好奇,但是看了一眼有些晕,功夫不够,哪天心情好翻开看看再。

到此,init过程结束。

 

参考:http://lirobo.blogspot.tw/2014/07/openwrt-boot.html

OpenWRT新框架的boot过程,布布扣,bubuko.com

OpenWRT新框架的boot过程

标签:style   blog   http   color   使用   strong   

原文地址:http://www.cnblogs.com/pied/p/3848361.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!