参考文档:

http://blog.csdn.net/jk110333/article/details/7616765
http://blog.chinaunix.net/uid-26598889-id-3060545.html

下面是我的理解:

总的流程是:1.CFE->2.linux->3./etc/preinit->4./sbin/init ->5./etc/inittab ->6./etc/init.d/rcS->7./etc/rc.d/S*

1.按照http://wiki.openwrt.org/doc/techref/process.boot中的描述,初始化从bootloader开始,会调用/etc/preinit脚本。 至于bootloader又是如何启动的,以及bootloader如何调用/etc/preinit的,这个以后再分析

2./etc/preinit脚本的分析:

#!/bin/sh     //注释:表示该脚本文件运行的时候 ,调用/bin/sh来解释
# Copyright (C) 2006 OpenWrt.org
# Copyright (C) 2010 Vertical Communications

export PATH=/bin:/sbin:/usr/bin:/usr/sbin
. /etc/diag.sh   //注释:. /etc/diag.sh" 就是将/etc/diag.sh脚本包含到本脚本中,等同于"source /etc/diag.sh",可以认为是C语言的#include。/etc/diag.sh脚本中定义了两个函数:set_led()和set_state(),是用来根据状态来点灯的 --- 想必运行openWRT的设备上都至少有:dmz,diag和power三个灯吧

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"

. /etc/functions.sh     //注释:定义一些函数
. /lib/functions/boot.sh  //注释:定义一些boot阶段要用到的函数,其中就定义了如下要用到的函数:boot_hook_init和boot_run_hook

//注释:如下是初始化5种hook,这5种hook用来处理/lib/preinit/*中的各类脚本文件

boot_hook_init preinit_essential
boot_hook_init preinit_main
boot_hook_init failsafe
boot_hook_init initramfs
boot_hook_init preinit_mount_root

//注释:按开头数字的顺序,依次执行/lib/preinit/中的各个脚本

for pi_source_file in /lib/preinit/*; do
    . $pi_source_file
done

//注释:上述这些脚本中的每一个,最后都会有如下的调用处理

#boot_hook_add preinit_main 某个脚本中自定义的函数
  #boot_hook_add preinit_mount_root 某个脚本中自定义的函数
  #boot_hook_add preinit_essential 某个脚本中自定义的函数
  #boot_hook_add failsafe 某个脚本中自定义的函数

#boot_hook_add initramfs 某个脚本中自定义的函数

#可以想见,这些脚本都是将各自脚本定义的函数,通过boot_hook_add挂接到了某个函数链上。而这些函数又分为了几类:preinit_main/preinit_mount_root/preinit_essential/failsafe/initramfs

boot_run_hook preinit_essential //注释:等上述脚本中定义的函数,都按照分类挂接好之后,则这里统一处理所有类型为:preinit_essential的函数

pi_mount_skip_next=false
pi_jffs2_mount_success=false
pi_failsafe_net_message=false

boot_run_hook preinit_main

//注释:再统一处理所有类型为:preinit_main的函数

#并且按照数字顺序,最后处理的是脚本99_10_run_init中的函数:
#运行 exec env - PATH=$pi_init_path $pi_init_env $pi_init_cmd 2>&0   其中pi_init_cmd为"/sbin/init"
#因此开始运行busybox的init命令。busybox的init命令执行inittab的脚本,此脚本位于/etc/inittab

3. 下面分析:/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

//注释:

  #sysinit为系统初始化运行的 /etc/init.d/rcS S boot脚本  
  #shutdown为系统重启或关机运行的脚本
  #tty开头的是,如果用户通过串口或者telnet登录,则运行/bin/ash --login
  #askfirst和respawn相同,只是在运行前提示"Please press Enter to activate this console."
//当前启动转到运行 /etc/init.d/rcS S boot,该脚本来自/etc/init.d/rcS

4.下面分析 /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"

//注释:由于在inittab中有:::sysinit:/etc/init.d/rcS S boot,故这里进入if分支

if [ "$1" = "S" ]; then
    run_scripts "$1" "$2" &   //注释:运行/etc/rc.d/目录下所有以S开头的脚本,而且还是后台运行(&表示后台运行)
else
    run_scripts "$1" "$2"
fi

5. /etc/rc.d/目录中有啥呢? 进入设备中的此目录,ls看一下,会发现:

K50dropbear           S39usb                    S59luci_dhcp_migrate
K90network            S40network              S60dnsmasq
K95luci_fixtime       S41wmacfixup          S60samba
K98boot                 S45firewall               S95done
K99umount            S50cron                   S96led
S02nvram               S50dropbear            S97watchdog
S05luci_fixtime       S50qos                    S98sysntpd
S05netconfig          S50telnet                 S99multiwan
S10boot                 S50uhttpd               S99sysctl

这么多以S开头的脚本,都是初始化时启动的。下面就选择其中的 S60samba 来分析吧。

6./etc/rc.d/S60samba  --- 实际上,S60samba -> ../init.d/samba , 其内容为:

#!/bin/sh /etc/rc.common    

//注释:引用/etc/rc.common脚本的处理,这里面会引用脚本:/etc/functions.sh,并且还有针对boot函数的定义,如下:

  boot() {
       start "$@"  //即缺省的boot实际就是start;那么这里调用 S60Samba中的start函数了  -- 如果我理解错了,请纠正我
  }

# Copyright (C) 2008-2011 OpenWrt.org

START=60

smb_header() {
    local interface
    config_get interface $1 interface "loopback lan"

# resolve interfaces
    local interfaces=$(
        include /lib/network
        scan_interfaces

local net
        for net in $interface; do
            local ifname
            config_get ifname "$net" ifname
            [ -n "$ifname" ] && {
                local ipaddr netmask
                config_get ipaddr  "$net" ipaddr
                config_get netmask "$net" netmask
                [ -n "$ipaddr" ] && echo -n "$ipaddr/${netmask:-255.255.255.255} "

local ip6addr
                config_get ip6addr "$net" ip6addr
                [ -n "$ip6addr" ] && echo -n "$ip6addr "
            }

echo -n "${ifname:-$net} "
        done
    )

local name workgroup description charset
    local hostname="$(uci_get system.@system[0].hostname)"

config_get name        $1 name        "${hostname:-OpenWrt}"
    config_get workgroup   $1 workgroup   "${hostname:-OpenWrt}"
    config_get description $1 description "Samba on ${hostname:-OpenWrt}"
    config_get charset     $1 charset     "UTF-8"

mkdir -p /var/etc
    sed -e "s#|NAME|#$name#g" \
        -e "s#|WORKGROUP|#$workgroup#g" \
        -e "s#|DESCRIPTION|#$description#g" \
        -e "s#|INTERFACES|#$interfaces#g" \
        -e "s#|CHARSET|#$charset#g" \
        /etc/samba/smb.conf.template > /var/etc/smb.conf

local homes
    config_get_bool homes $1 homes 0
    [ $homes -gt 0 ] && {
        cat <<EOT >> /var/etc/smb.conf

[homes]
    comment     = Home Directories
    browsable   = no
    read only   = no
    create mode = 0750
EOT
    }

[ -L /etc/samba/smb.conf ] || ln -nsf /var/etc/smb.conf /etc/samba/smb.conf
}

smb_add_share() {
    local name
    local path
    local users
    local read_only
    local guest_ok
    local create_mask
    local dir_mask

config_get name $1 name
    config_get path $1 path
    config_get users $1 users
    config_get read_only $1 read_only
    config_get guest_ok $1 guest_ok
    config_get create_mask $1 create_mask
    config_get dir_mask $1 dir_mask

[ -z "$name" -o -z "$path" ] && return

echo -e "\n[$name]\n\tpath = $path" >> /var/etc/smb.conf
    [ -n "$users" ] && echo -e "\tvalid users = $users" >> /var/etc/smb.conf
    [ -n "$read_only" ] && echo -e "\tread only = $read_only" >> /var/etc/smb.conf
    [ -n "$guest_ok" ] && echo -e "\tguest ok = $guest_ok" >> /var/etc/smb.conf
    [ -n "$create_mask" ] && echo -e "\tcreate mask = $create_mask" >> /var/etc/smb.conf
    [ -n "$dir_mask" ] && echo -e "\tdirectory mask = $dir_mask" >> /var/etc/smb.conf
}

start() { //注释:这是启动时实际调用的地方
    config_load samba   //注释:config_load在/etc/functions.sh中定义,其主体是:uci_load "$@" 。没找到进一步的函数定义,我猜测这里实际就是要加载配置文件:/etc/config/samba  --- 如果我猜错,请纠正我。特别提出的是:/etc/config/samba就是符合openWRT的uci要求的配置文件了。openWRT本身就是通过调整此配置文件,来控制samba进程的

    config_foreach smb_header samba   //注释:这里会调用此脚本中定义的smb_header()函数,作用是解析/etc/config/samba文件中的"config samba"栏目中的各个参数,并写入到/vat/etc/smb.conf文件中
    config_foreach smb_add_share sambashare //注释:这里会调用此脚本中定义的smb_add_share()函数,作用是解析/etc/config/samba文件中的"config sambashare"栏目中的各个参数,并写入到/var/etc/smb.conf文件中

service_start /usr/sbin/smbd -D  //注释:启动服务进程。这个进程是要读取文件/var/etc/smb.conf的。即:samba进程本身是不识别/etc/config/samba的,而只识别/var/etc/smb.conf文件
}

stop() {
    service_stop /usr/sbin/smbd
}

openWRT自学---初始化过程和主要脚本的分析的更多相关文章

  1. 【Spring源码分析】非懒加载的单例Bean初始化过程(下篇)

    doCreateBean方法 上文[Spring源码分析]非懒加载的单例Bean初始化过程(上篇),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下 ...

  2. Spring源码分析:非懒加载的单例Bean初始化过程(下)

    上文Spring源码分析:非懒加载的单例Bean初始化过程(上),分析了单例的Bean初始化流程,并跟踪代码进入了主流程,看到了Bean是如何被实例化出来的.先贴一下AbstractAutowireC ...

  3. YARN分析系列之三 -- 从脚本入口分析 ResourceManager的初始化过程

    1. 由脚本找到 RM 主类 这部分,我们从脚本作为入口去逐步深入ResourceManager源码. 从 Hadoop 官方文档 中可以看到 ResourceManager 的启动命令为: Usag ...

  4. linux文件系统初始化过程(3)---加载initrd(上)

    一.目的 本文主要讲述linux3.10文件系统初始化过程的第二阶段:加载initrd. initrd是一个临时文件系统,由bootload负责加载到内存中,里面包含了基本的可执行程序和驱动程序.在l ...

  5. linux文件系统初始化过程(6)---执行init程序

    一.目的 内核加载完initrd文件后,为挂载磁盘文件系统做好了必要的准备工作,包括挂载了sysfs.proc文件系统,加载了磁盘驱动程序驱动程序等.接下来,内核跳转到用户空间的init程序,由ini ...

  6. Linux系统LVM逻辑卷创建过程以及自动化脚本

    转至:https://cloud.tencent.com/developer/article/1068328 Linux系统LVM逻辑卷创建过程以及自动化脚本 2018-03-21阅读 6300   ...

  7. Java类变量和成员变量初始化过程

    一.类的初始化 对于类的初始化:类的初始化一般只初始化一次,类的初始化主要是初始化静态成员变量. 类的编译决定了类的初始化过程. 编译器生成的class文件主要对定义在源文件中的类进行了如下的更改: ...

  8. 【初探Spring】------Spring IOC(三):初始化过程---Resource定位

    我们知道Spring的IoC起到了一个容器的作用,其中装得都是各种各样的Bean.同时在我们刚刚开始学习Spring的时候都是通过xml文件来定义Bean,Spring会某种方式加载这些xml文件,然 ...

  9. 【初探Spring】------Spring IOC(二):初始化过程---简介

    首先我们先来看看如下一段代码 ClassPathResource resource = new ClassPathResource("bean.xml"); DefaultList ...

随机推荐

  1. iOS开发——给ImageView添加点击事件

          给ImageView添加点击事件   1: cell.pictureView.userInteractionEnabled = YES; 2: UITapGestureRecognizer ...

  2. 利用Java位运算符,完成Unsigned转换(无符号)

    方案二:利用Java位运算符,完成Unsigned转换. 正常情况下,Java提供的数据类型是有符号signed类型的,可以通过位运算的方式得到它们相对应的无符号值,参见几个方法中的代码: publi ...

  3. FTTB FTTC FTTH FTTO FSA

    FTTB Fiber to The Building 光纤到楼 FTTC Fiber to The Curb 光纤到路边 FTTH Fiber to The Home 光纤到家 FTTO Fiber ...

  4. springBoot框架不同环境读取不同的配置文件

    1. 3个配置文件(更多环境可以建多个): application.properties  (公共配置文件) application-dev.properties  (开发环境) applicatio ...

  5. Coherence对象压缩以及对象大小计算

    1.通过util.zip带的gzip压缩程序  Coherence对象压缩程序如下 package coherencetest; import com.tangosol.net.CacheFactor ...

  6. ylbtech-LanguageSamples-CollectionClasses(集合类)

    ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-CollectionClasses(集合类) 1.A,示例(Sample) 返回顶部 “ ...

  7. min-height IE6的解决方案

    selector { min-height:500px; height:auto !important; height:500px; } 因为IE6中当内容大于容器高度或宽度时,就会撑破容器.并且在同 ...

  8. 利用github和git命令,将本地项目共享到服务器上

    一.步骤 1. 创建项目根目录 mkdir 文件夹名 2. 初始化文件夹 git init 3. 配置用户名和邮箱(第一次配置后,不需要再登录) git config user.name 名字 git ...

  9. web开发者的博客

    一.  Jerry Qu https://imququ.com/post/sth-about-switch-to-https-2.html 点评:博客做的比较好,样式不错. http知识比较深.

  10. hdu 4723 How Long Do You Have to Draw(贪心)

    How Long Do You Have to Draw Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...