【智能路由器】源码追踪路由器启动过程

首先来张图简要的从源码的角度展示一下Linux内核的路由器启动过程(图片看不清的话建议放大后查看):
路由器启动


下面的重点是关注一下,kernel启动后,从第一个用户进程执行,到系统启动完毕,做了哪些事。

1. 路由器内核启动执行流程
UBoot在设置好一些环境参数后会将PC指针指向内核代码,从此CPU就交由Linux全权掌控。网上很多详解Linux启动的文章,在此就不多此一举的分析代码了,但还是画个流程图。
这里写图片描述

注意到流程图中的蓝色方框,init程序启动后会根据inittab中的配置来运行相应的程序或脚本。一般inittab会放到/etc文件加下,但是路由器中是在/etc_ro文件夹下。找到inittab文件,查看,发现只有如下两行信息:

::sysinit:/etc_ro/rcS
ttyS1::respawn:/bin/sh

2. 理解inittab文件作用机制
解读:Inittab文件每行有四个字段,字段之间用“:”分开,形式如下:
这里写图片描述

ID:入口唯一标识符,它是一个字符串,getty和mingetty等程序项,要求id和tty的编号相同。
Runlevel:配置行适用的运行级别,着这里可填入多个运行级别,比如12345或者25等
运行级别

Action:运行方式如下表:
运行方式

Process:所要执行的shell命令,任何合法的shell语法均适用于该字段。

现在,我们再来解读inittab里的两行信息:

::sysinit:/etc_ro/rcS    //不论在哪个执行等级,都将执行/etc_ro/rcS脚本
ttyS1::respawn:/bin/sh  //启动并监视/bin/sh,若/bin/sh终止则重启它

/etc_ro/rcS:脚本完成了一些系统初始化工作,它完成了磁盘检查,加载硬件模块一起其他一些需要优先执行的任务。
/bin/sh:脚本解释器,作用不解释。

知道了init程序加载inittab文件的机制后,如果我们想在开机的时候执行某些程序或脚本就可以借助inittab文件实现,相信你知道怎么做了。
设一道题目作为练习:
写一个脚本文件命名mystartmount.sh,要求系统在开机时执行该脚本,打印hello world信息。

3. init第一个启动的脚本文件rcS
查看rcs文件,内容及解释如下:
rcS脚本
从图片中的代码可以看到,该文件除了创建一些目录节点外,启动了Telnet,将nvram_daemon放入后台运行,还启动了用户程序init_system。从名字上理解似乎这个应用程序是初始化系统的,但是我们的Linux系统都已经跑起来了,还要它初始化什么呢?
这个init_system的程序到底做了什么,请看下节。

4. init_system做了什么
init_system的源码位于user/lighttpd-1.4.20/cgi_src/目录下,查看init_system.c,找到main函数:

int main(int argc, char *argv[])
{
    if (argc < 2) {
        usage();
        return -1;
    }
    if (!strcmp(argv[1], "start")) {
        if (set_default() < 0)
            return -1;
        init_internet();
        do_system("lighttpd -f /etc_ro/lighttpd/lighttpd.conf -m /etc_ro/lighttpd/lib");
    } else if (!strcmp(argv[1], "restart")) {
        init_internet();
    } else {
        usage();
    }
    return 0;
}

函数除了调用了do_system启动Lighttpd外,还调用init_Internet()。刨根问个底吧,查看init_Internet()代码,发现该函数在调用Lighttpd服务器里的一些CGI之前,运行了Internet.sh脚本,这是/sbin目录下的shell脚本。

static void init_internet(void)
{
    do_system("internet.sh");
    do_system("/etc_ro/lighttpd/www/cgi-bin/wireless.cgi init");
    do_system("/etc_ro/lighttpd/www/cgi-bin/firewall.cgi init");
    do_system("/etc_ro/lighttpd/www/cgi-bin/adm.cgi init");
    do_system("/etc_ro/lighttpd/www/cgi-bin/internet.cgi init");
#if defined CONFIG_RALINKAPP_SWQOS || defined CONFIG_RALINKAPP_HWQOS
    do_system("/etc_ro/lighttpd/www/cgi-bin/qos.cgi init");
#endif
#if defined CONFIG_USER_STORAGE
    do_system("/etc_ro/lighttpd/www/cgi-bin/nas.cgi init");
    do_system("/etc_ro/lighttpd/www/cgi-bin/usb.cgi init");
#endif
}

我们知道,系统下的internet.sh是随开机启动的。我们又可以联想到,假如我们要在开机执行一个我们自定义的脚本,完全可以将我们的脚本文件放在internet.sh里面调用,当然也可以放在rcS脚本里面调用,其实讲了这么多主要用意在此。internet.sh本身的内容我们现在不必理会,知道它是处理进行一些网络设置就行了。

至此,Linux系统以及一些开机启动的附属程序及shell脚本都启动完成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值