• 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
    }  
       
  • 相关阅读:
    iOS应用程序生命周期(前后台切换,应用的各种状态)详解
    Urlrewrite
    下载文件、根据链接生成二维码
    三级联动
    easy-ui的datagrid
    $.extend、$.fn.extend
    windows.open、 window.location.href
    JS小整理
    Jsp数字格式化
    同时执行多个$.getJSON() 出现数据混乱的问题的解决
  • 原文地址:https://www.cnblogs.com/lagujw/p/3683882.html
Copyright © 2020-2023  润新知