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

来源:互联网 发布:ios11.1 4g网络不好 编辑:程序博客网 时间:2024/05/12 08:27

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


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

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

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

::sysinit:/etc_ro/rcSttyS1::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脚本都启动完成!

1 0