一、OpenWrt启动过程分析

转自: http://www.eehello.com/?post=107

总结一下OpenWrt的启动流程:1.CFE->2.linux->3./etc/preinit->4./sbin/init ->5./etc/inittab ->6./etc/init.d/rcS->7./etc/rc.d/S* ->8.

OpenWrt是一个开放的linux平台,主要用于带wifi的无线路由上。

类似于Ubuntu、Red Hat、之类的linux发行版本,它也有一套自己的启动流程。下面,我就以我的Linksys 的WRT54G为平台介绍一下,OpenWrt的启动流程。

 1.首先,CFE(common firmware environment)--它就是一个bootloader,类似u-boot,redboot之类,有点broadcom公司御用之嫌--

最先启动。它的任务只是创造一个简单的环境,让系统先运行起来。除了能够跳转到特定地址上启动操作系统(如Linux)外,

它还能让你download东西到上面,比如download一个linux,然后启动它。

另外,值得一提的是,CFE在启动之后会有1,2秒的时间等待由tftp上传的内核并烧写到flash上,

这就给一些操作系统损坏但CFE还能工作的"砖头"板一个起死回生的机会。请注意一旦linux启动之后,将由linux全部接管系统,

2.这时候就没CFE什么事情了。唯一的瓜葛是CFE传递给内核一个命令行的参数,这个可以在linux启动起来之后用下面的命令查看:

root@OpenWrt:/# cat /proc/cmdline

console=ttyS0,115200 mtdparts=spi_flash:1m(u-boot)ro,3m(kernel),-(rootfs)

之后,linux系统启动起来了。它使用类似如下的脚本命令来解析cmdline:

for x in $(cat /proc/cmdline); do

case $x in

init=*)

init=${x#init=}

;;

root=*)

ROOT=${x#root=}

case $ROOT in

LABEL=*)

ROOT="/dev/disk/by-label/${ROOT#LABEL=}"

;;

UUID=*)

ROOT="/dev/disk/by-uuid/${ROOT#UUID=}"

;;

esac

;;

rootflags=*)

ROOTFLAGS="-o ${x#rootflags=}"

;;

cryptopts=*)

cryptopts="${x#cryptopts=}"

;;

nfsroot=*)

NFSROOT="${x#nfsroot=}"

;;

nfsopts=*)

NFSOPTS="-o ${x#nfsopts=}"

;;

boot=*)

BOOT=${x#boot=}

;;

resume=*)

RESUME=${x#resume=}

;;

noresume)

NORESUME=y

;;

quiet)

quiet=y

;;

ro)

readonly=y

;;

rw)

readonly=n

;;

debug)

debug=y

exec >/tmp/initramfs.debug 2>&1

set -x

;;

break=*)

break=${x#break=}

;;

break)

break=premount

;;

esac

done

对于OpenWrt这个cmdline的意思就是:root=/dev/mtdblock2 文件系统在第三个flash分区上(mtdblock0,1,2);

rootfstype=squashfs,jffs2 文件系统类型是squashfs和jffs2(为什么两种类型,目前还不清楚,

不过可以确定OpenWrt使用了较为复杂的文件系统,实现了squashfs的压缩和jffs2的可写 );

init=/etc/preinit 执行该初始化,noinitrd console=ttyS0,115200

没有initrd和console口设定。

3.

init=/etc/preinit 是linux会执行的初始化,具体内容如下:

root@OpenWrt:/# cat /etc/preinit

#!/bin/sh

# Copyright (C) 2006 OpenWrt.org

export PATH=/bin:/sbin:/usr/bin:/usr/sbin

. /etc/diag.sh

failsafe_ip() {

ifconfig $ifname 192.168.1.1 netmask 255.255.255.0 broadcast 192.168.1.2 55 up

}

failsafe() {

[ -n "$ifname" ] && grep "$ifname" /proc/net/dev >/dev/null && {

failsafe_ip

netmsg 192.168.1.255 "Entering Failsafe!"

telnetd -l /bin/login <> /dev/null 2>&1

}

lock /tmp/.failsafe

ash --login

}

mount proc /proc -t proc

mount sysfs /sys -t sysfs

size=$(awk '/MemTotal:/ {l=5242880;mt=($2*1024);print((s=mt/2)<l)&&(mt>l)?mt-l:s }' /proc/meminfo)

mount tmpfs /tmp -t tmpfs -o size=$size,nosuid,nodev,mode=1777

if grep devfs /proc/filesystems > /dev/null; then

mount devfs /dev -t devfs

M0=/dev/pty/m0

M1=/dev/pty/m1

HOTPLUG=/sbin/hotplug-call

elif [ -x /sbin/hotplug2 ]; then

mount -t tmpfs tmpfs /dev -o size=512K

mknod /dev/console c 5 1

/sbin/hotplug2 --coldplug --set-rules-file /etc/hotplug2-init.rules

/sbin/hotplug2 --no-coldplug --persistent --set-rules-file /etc/hotplug2 -init.rules &

M0=/dev/ptmx

M1=/dev/ptmx

HOTPLUG=

elif [ -x /sbin/udevd ]; then

mount -n -t tmpfs -o mode=0755 udev /dev

/sbin/udevd --daemon

/sbin/udevtrigger

/sbin/udevsettle

M0=/dev/pty/ptmx

M1=/dev/pty/ptmx

HOTPLUG=

fi

mkdir -p /dev/pts /dev/shm

mount devpts /dev/pts -t devpts

# the shell really doesn't like having stdin/out closed

# that's why we use /dev/pty/m0 and m1 as replacement

# for /dev/console if there's no serial console available

dd if=/dev/console of=/dev/null bs=1 count=0 >/dev/null 2>/dev/null && {

M0=/dev/console

M1=/dev/console

}

exec <$M0 >$M1 2>&0

echo "- preinit -"

echo "Press CTRL-C for failsafe"

trap 'FAILSAFE=true' INT

trap 'FAILSAFE=true' USR1

[ -e /etc/preinit.arch ] && . /etc/preinit.arch

set_state preinit

echo "$HOTPLUG" > /proc/sys/kernel/hotplug

eval ${FAILSAFE:+failsafe}

lock -w /tmp/.failsafe

if [ -z "$INITRAMFS" ]; then

mount_root

[ -f /sysupgrade.tgz ] && {

echo "- config restore -"

cd /

mv sysupgrade.tgz /tmp

tar xzf /tmp/sysupgrade.tgz

rm -f /tmp/sysupgrade.tgz

sync

}

echo "- init -"

exec /sbin/init

fi

可见,它主要是挂载一些系统需要的文件系统,例如tmpfs,proc和sysfs(是否真正挂载取决于内核是否2.6的)。

并且会准备设备节点和故障恢复(failsafe)的准备。(这里还没看懂 )

 4.

最后,exec /sbin/init启动文件系统,在OpenWrt上也就是busybox的init程序。

它会自动分析/etc/inittab这个文件,其内容解释详见busybox网站的cmd help。

5.

/etc/inittab的内容:

::sysinit:/etc/init.d/rcS S boot

::shutdown:/etc/init.d/rcS K stop

tts/0::askfirst:/bin/ash --login

ttyS0::askfirst:/bin/ash --login

tty1::askfirst:/bin/ash --login

6.

运行/etc/init.d/rcS:

#!/bin/sh

# Copyright (C) 2006 OpenWrt.org

run_scripts() {

for i in /etc/rc.d/$1*; do

[ -x $i ] && $i $2 2>&1

done | $LOGGER

}

LOGGER="cat"

[ -x /usr/bin/logger ] && LOGGER="logger -s -p 6 -t sysinit"

if [ "$1" = "S" ]; then

run_scripts "$1" "$2" &

else

run_scripts "$1" "$2"

fi

  7.

将执行/etc/rc.d/S*这些脚本:

root@OpenWrt:/# ls /etc/rc.d/S*

/etc/rc.d/S10boot

/etc/rc.d/S50cron

/etc/rc.d/S60led

/etc/rc.d/S20fstab

/etc/rc.d/S50dropbear

/etc/rc.d/S95done

/etc/rc.d/S39usb

/etc/rc.d/S50uhttpd

/etc/rc.d/S97watchdog

/etc/rc.d/S40network

/etc/rc.d/S50telnet

/etc/rc.d/S99sysctl

/etc/rc.d/S45firewall /

etc/rc.d/S60dnsmasq

按照数字从小到大的顺序执行。

二、实现自启动脚本

OpenWRT的启动脚本放在 /etc/init.d 目录下,而系统开机时自动运行/etc/rc.d目录下的脚本。所以在rc.d目录下、有init.d下脚本的链接文件。

整理一下

05 defconfig //加载默认参数

10 boot //启动

39 usb // 加载usbfs

40 network // 设置网卡参数

45 firewall // 防火墙

50 dropbear // sshd server

50 cron // .....

50 telnet // 如果没有修改root密码,则启动telnet server

60 dnsmasq // DHCP 和 DNS 服务端

95 done // ...

96 led // 指示灯

97 watchdog // ...

99 sysctl // 最后,进行必要的内核参数调整

然后,我们加入自己的脚本,实现模块驱动的加载、应用程序的开机自启动等。

首先在/etc/init.d里添加需要启动的shell脚本

例如:

vim startCamera

内容:

#!/bin/sh /etc/rc.common
# /init.d/startCamera
START=50
start()
{
./opt/ipnc/system_server &
}
stop()
{
killallsystem_server
}

之后还需要在rc.d目录下做一个链接,启动时系统会按顺序启动rc.d目录下的脚本链接,对应执行init.d目录下的启动脚本。脚本的命名要符合系统规范,init.d下telnet脚本在rc.d目录下的链接文件名为S50telnet。所以链接文件要在脚本名前加S+启动顺序数字,启动顺序要等系统进行完必要的初始化。所以我们命名为S95+脚本名。

命令:ln -s /etc/init.d/startCamera /etc/rc.d/S95startCamera

重启,即可

现在实现了应用程序的开机自启动。

OpenWrt启动过程分析+添加自启动脚本【转】的更多相关文章

  1. OpenWrt启动过程分析

    openwrt是通过一系列shell脚本进行启动流程的组织,下面是启动流程的提纲.如 果想详细了解启动的过程,则需要仔细走读脚本文件. 1. 在make menuconfig 选择target平台 B ...

  2. linux 开机自启动脚本

    在/etc/rc.local文件中添加自启动命令(其中一种方法) 1.案例,就用博主本人之前发的博文 “nginx + flask + uwsgi + centos + python3 搭建web项目 ...

  3. linux添加开机自启动脚本示例详解

    linux下(以RedHat为范本)添加开机自启动脚本有两种方法,先来简单的; 一.在/etc/rc.local中添加如果不想将脚本粘来粘去,或创建链接什么的,则:step1. 先修改好脚本,使其所有 ...

  4. 转载:ubuntu 下添加简单的开机自启动脚本

    转自:https://www.cnblogs.com/downey-blog/p/10473939.html linux下添加简单的开机自启动脚本 在linux的使用过程中,我们经常会碰到需要将某个自 ...

  5. openwrt启动过程(脚本)

    来源:  http://wiki.openwrt.org/doc/techref/preinit_mount#first.boot 基本的openwrt启动顺序为: 1.boot loader loa ...

  6. openwrt 为软件包添加服务

    手动修改 rc.local 加入也可以实现自启动,缺点手动修改太麻烦,停止只能用 kill . 配置成服务最方便了,可以启用或禁用,启动,停止,重启非常方便. 在openwrt 中使用服务 servi ...

  7. 【转】linux 编译安装nginx,配置自启动脚本

    linux 编译安装nginx,配置自启动脚本 本文章来给各位同学介绍一篇关于linux 编译安装nginx,配置自启动脚本教程,希望有需要了解的朋友可一起来学习学习哦. 在公司的suse服务器装ng ...

  8. linux 编译安装nginx,配置自启动脚本

    本文章来给各位同学介绍一篇关于linux 编译安装nginx,配置自启动脚本教程,希望有需要了解的朋友可一起来学习学习哦. 在公司的suse服务器装nginx,记录下安装过程: 参照这篇文章:Linu ...

  9. Ubuntu14.04设置开机自启动脚本

    方法一.编辑rc.loacl脚本  Ubuntu开机之后会执行/etc/rc.local文件中的脚本,所以我们可以直接在/etc/rc.local中添加启动脚本.在 exit 0 前面添加好脚本代码, ...

随机推荐

  1. ubuntu 14.04下使用fcitx时将caps lock映射为ctrl

    在~/.xprofile中加入 setxkbmap -option caps:ctrl_modifier 要弄成全局的就在 /etc/X11/Xsession.d/ 里面找个文件塞进去. archli ...

  2. 隐藏技能go:linkname

    来源:https://blog.csdn.net/lastsweetop/article/details/78830772 什么是go:linkname 指令的格式如下: //go:linkname ...

  3. 【51Nod1405】树上距离和 二次扫描与换根法

    题目大意:给定一棵 N 个点的边权均为 1 的树,依次输出每个点到其他各个点的距离和. 题解:首先任意选定一个节点为根节点,比如 1,第一遍 dfs 遍历树求出子树大小.树上前缀和.第二遍 dfs 遍 ...

  4. mac 上sublime3安装编码插件

    我们常常会遇到这样的问题:我们使用 mac 的时候,从 windows 上接受过来的文档通过 sublime3打开之后就是乱码,这个时候需要安装相对应的编码插件才能正常查看. 1. 打开 sublim ...

  5. go struct结构体

    struct结构体 用来自定义复杂数据结构 struct里面可以包含多个字段(属性),字段可以是任意类型 struct类型可以定义方法,注意和函数的区分 struct类型是值类型 struct类型可以 ...

  6. 数据分析工具urule

    Python统计学书籍 https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-13911786811.22.6431353b4F5iw1& ...

  7. 记录一次iptables端口转发的配置

    需求是公网访问2.2.2.22的80端口,直接转发到内网的192.100.100.178的80端口上. 代理服务器的,两个不同的网卡 eth0 2.2.2.22 eth1 192.100.100.10 ...

  8. Codeforces 526D Om Nom and Necklace (KMP)

    http://codeforces.com/problemset/problem/526/D 题意 给定一个串 T,对它的每一个前缀能否写成 A+B+A+B+...+B+A+B+A+B+...+B+A ...

  9. 基于Selenium的Web自动化框架增强篇

    在写完上一篇“基于Selenium的Web自动化框架”(http://www.cnblogs.com/AlwinXu/p/5836709.html)之后一直没有时间重新审视该框架,正好趁着给同事分享的 ...

  10. readn.c

    #include <errno.h> #include <unistd.h> ssize_t readn(int fd, void *vptr, size_t n) { siz ...