查看“第一课--MicroWRT 系统启动流程”的源代码
←
第一课--MicroWRT 系统启动流程
跳转至:
导航
、
搜索
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
{| style="width: 800px;" |- | 任何系统的启动都是开发人员首要关注的问题,因为只有了解了系统的启动流程和启动机制,才能 真正掌握一个系统,如果对启动的启动不熟悉的话,是不可能真正用好一个系统,openwrt 系统也不例 外,它的启动和一般的嵌入式系统启动还有所区别,本教程就分析一下openwrt 的启动流程。 ==内核补丁== 在openwrt 的官网上面下载的源码,其中包括了一些内核补丁,这里究竟为什么要给内核做补丁呢? 因 为openwrt 为了支持更多的路由器,更多的操作和openwrt 特有的一些内核功能,linux 源码是不具备 的,这样openwrt 为了增加这些功能,就需要在linux 官网上面下载的源代码中做一些修改,在这里体 现为给linux 源码打补丁。Openwrt 源码中的linux 补丁文件放在target/linux/generic 文件下面,有对于 不同版本的linux 内核补丁文件。我们以 3.10 版本的内核为例,它的补丁文件在patches-3.10 目录下面。这里是所有的内核补丁文件,在编译openwrt 的时候,会首先把他们拷贝到内核目录下面, 然后在内核上面打上这些补丁,然后再编译内核。咱们首先分析他对于linux 启动的补丁,它的名字是 921-use_preinit_as_init.patch,我们可以看看他的内容: ---a/init/main.c ---b/init/main.c @@ -840,7 +840,8 @@ static int __ref kernel_init(void *unuse pr_err("Failed to execute %s. Attempting defaults...\n", execute_command); } -if (!run_init_process("/sbin/init") || +if (!run_init_process("/etc/preinit") ||!run_init_process("/sbin/init") ||!run_init_process("/etc/init") || !run_init_process("/bin/init") ||!run_init_process("/bin/sh")) 可以看到他它修改linux 内核中默认的启动项,可以看到它首先启动“/etc/preinit”,它是个脚本,我们就从这个脚本说起。 ==Preinit 介绍== Preinit 脚本在etc 目录下面,首先先看看他的内容: #!/bin/sh # Copyright (C) 2006 OpenWrt.org # Copyright (C) 2010 Vertical Communications [ -z "$PREINIT" ] && exec /sbin/init export PATH=/bin:/sbin:/usr/bin:/usr/sbin pi_ifname= pi_ip=192.168.1.1 pi_broadcast=192.168.1.255 pi_netmask=255.255.255.0 fs_failsafe_ifname= fs_failsafe_ip=192.168.1.1 fs_failsafe_broadcast=192.168.1.255 fs_failsafe_netmask=255.255.255.0 fs_failsafe_wait_timeout=2 pi_suppress_stderr="y" pi_init_suppress_stderr="y" pi_init_path="/bin:/sbin:/usr/bin:/usr/sbin" pi_init_cmd="/sbin/init" . /lib/functions.sh boot_hook_init preinit_essential boot_hook_init preinit_main boot_hook_init failsafe boot_hook_init initramfs boot_hook_init preinit_mount_root for pi_source_file in /lib/preinit/*; do . $pi_source_file done boot_run_hook preinit_essential pi_mount_skip_next=false pi_jffs2_mount_success=false pi_failsafe_net_message=false boot_run_hook preinit_main 这就是个bash 脚本,前半部分只是定义了一些变量,先记住他们的内容即可,有两个函数是我们需要 了解的,boot_hook_init 和boot_run_hook。他们定义在/lib/functions/preinit.sh 文件中,boot_hook_init 是初始化一个函数队列,boot_run_hook 是运行一个函数队列,还有一个这个文件没有体现,后面的文 件中会遇到,这里说明一下,boot_book_add 这个是在一个函数队列中添加一个函数。然后就是执行: for pi_source_file in /lib/preinit/*; do . $pi_source_file done 循环执行/lib/preinit 目录下面的脚本,这里简要分析一个,这里分析02_default_set_state,首先看看他的内容 #!/bin/sh define_default_set_state(){ ./etc/diag.sh } boot_hook_add preinit_main define_default_set_state 可以看到它就是在preinit_main 函数队列中增加一个函数,这个函数就是简单的执行一个脚本。当运行 preinit_main 的时候,队列中的所有函数就会依次执行。其他文件可以自行分析,都比较简单。 最后在preinit 脚本中执行preinit_main。执行完这个脚本之后init 进程会根据inittab 文件执行其他的启 动项。 ==Inittab 介绍== inittab 为linux 初始化文件系统时init 初始化程序用到的配置文件。这个文件负责设置init 初始化程序初 始化脚本在哪里;每个运行级初始化时运行的命令; 开机、关机、重启对应的命令;各运行级登陆时所运 行的命令。 如果存在/etc/inittab 文件,Busybox init 程序解析它,然后按照它的指示创建各种子进程,否则使用默 认的配置创建子进程. /etc/inittab 文件中每个条目用来定义一个子进程,并确定它的启动方法,格式如下 <id> : <runlevels> : <action> : <process> 1、id :表示这个子进程要使用的控制台,如果省略,则使用与init 进程一样的控制台. 2、runlevels:这个字段没有意义,可以省略。在linux 有意义. 3、action:表示init 进程如何控制这个子进程,具体取值见下表. 4、process:要执行的程序,它可以是可执行程序,也可以是脚本.如果process 字段前有“-”字符,这 个程序被称为“交互的”. {|class="wikitable" ! rowspan="1" | 名称 || 执行条件 || 说明 |- | sysinit || 系统启动后最先执行|| 指定初始化脚本路径,只执行一次,init进程等待它结束才继续执行其他动作 |- | wait || 系统执行完sysinit进城后|| 只执行一次,init进程等待它结束才能执行其他动作 |- | once || 系统执行完wait进程后|| 只执行一次,init进程不等待它结束 |- | respawn||启动完once进程后 || init进程监测发现子进程退出时,重新启动它,永不结束 |- | askfirst|| 启动完respawn进程后|| 与respawn类似,不过init进程先输出“please press Enter toactivate this console", 等用户输入回车后才启动子进程 |- | shutdown||当系统关机时 || 即重启,关闭系统时执行的程序 |- | restart||当系统重启时 || init进程重启时执行的程序,通常init程序本身先重新读取,解析/etc/inittab 文件,在执行 restart程序 |- | ctrl+alt+del||按下Ctrl+Alt+Del键时 || 按Ctrl+Alt+Del组合键时执行的程序 |} 先看看/etc/inittab 中的内容: ::syhsinit:/etc/init.d/rcs_S boot ::shutdown:/etc/init.d/rcs_K shutdown ::askconsole:/bin/ash --login 从上面的分析可以看出它在开机启动的时候执行/etc/init.d/rcS 脚本,以前是有/etc/init.d/rcS 脚本的, 现在的openwrt 已经去掉了这个脚本文件,只要有rcS S boot 这几个参数就可以,但是功能是有的 就是按顺序执行/etc/rc.d 下面的各个脚本,以S 开头代表启动的时候执行的脚本,与命令行中的S 对应, 以K 开头的代表关机的时候需要执行的脚本,与命令行中的K 对应。 ==总结== 从上面的分析我们可以总结一下 openwrt的启动流程如下: /etc/preinit->/lib/preinit/*->/etc/inittab->/etc/rc.d/S* |}
返回至
第一课--MicroWRT 系统启动流程
。
导航菜单
个人工具
创建账户
登录
名字空间
页面
讨论
变种
视图
阅读
查看源代码
查看历史
更多
搜索
Welcome
首页
创客大赛
大赛详情
3D打印
安装月球车
图形化编程
操控月球车
升级月球车
编程工具下载
软件下载
Arduino
Processing
Mixly
Scratch
模块套件
Microduino 102
mCookie 102
mCookie 202
mCookie 302
IBC
其他
应用套件
四轴飞行器
平衡车
小车CUBE
音乐播放器
刷卡音乐播放器
wifi气象站
彩虹音乐触摸灯
分贝检测仪
迎门汇报
LED点阵时钟
LED点阵屏幕
硬件
mCookie
Sensor
Microduino
MicroWrt
MicroNux
MicroRobot-Core
MicroRobot-CoreESP
ideaBoard
ideaBox
MicroMV
MicroAI
帮助
常见问题
帮助
工具
链入页面
相关更改
特殊页面
页面信息