zoukankan      html  css  js  c++  java
  • openWRT自学---初始化过程和主要脚本的分析--转

    参考文档:

    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 " [$name] path = $path" >> /var/etc/smb.conf
        [ -n "$users" ] && echo -e " valid users = $users" >> /var/etc/smb.conf
        [ -n "$read_only" ] && echo -e " read only = $read_only" >> /var/etc/smb.conf
        [ -n "$guest_ok" ] && echo -e " guest ok = $guest_ok" >> /var/etc/smb.conf
        [ -n "$create_mask" ] && echo -e " create mask = $create_mask" >> /var/etc/smb.conf
        [ -n "$dir_mask" ] && echo -e " directory 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
    }

  • 相关阅读:
    Django对静态文件的处理——部署阶段
    使用Django来处理对于静态文件的请求
    Django1.7如何配置静态资源访问
    Spring WebSocket中403错误解决
    FastJSON JSONObject 字段排序 Feature.OrderedField
    国际化(i18n) 各国语言缩写
    【转】java.io.Closeable接口
    【转】spring bean 卸载
    This content should also be served over HTTPS
    Failed to close the ServletOutputStream connection cleanly, Broken pipe
  • 原文地址:https://www.cnblogs.com/s08243/p/7718743.html
Copyright © 2011-2022 走看看