• linux 文件系统sysvinit 流程分析


    参考网上许多的教程。

    然后有一下相关的笔记:

    kernel 在挂载完文件系统后,会执行第一个进程init 

    这个进程的PID为1

    这个进程是所有进程的父进程

    init 进程,首先要去读取inittab中的数据,根据这里面的数据去执行相关的初始化。

    在inittab  可以指定默认的运行级别

      

    id:5:initdefault:

    还会规定第一个执行的程序

    si::sysinit:/etc/init.d/rcS
    //指定单用户模式
    ~~:S:wait:/sbin/sulogin

    在TI的板子上还规定终端的显示的开关

    0:2345:respawn:/sbin/getty 115200 ttyO0

    这里提到,他规定下一个执行的是/etc/init.d/rcS

    在/etc/init.d/rcS 内又做了哪些工作呢?

    PATH=/sbin:/bin:/usr/sbin:/usr/bin                                 //设置环境变量             
    runlevel=S                                                                      //设置运行级别
    prevlevel=N                                                                     
    umask 022                                                                       //设置默认权限补码
    export PATH runlevel prevlevel                                          //对外发布这些变量
    trap ":" INT QUIT TSTP
     //这里话的含义是忽略ctrl + c中断信号
    exec /etc/init.d/rc S    //运行/etc/init.d/rc    并加一个参数S

    下面进入rc文件分析

    1 # rc        This file is responsible for starting/stopping                      
    2 #       services when the runlevel changes.                                     
    3 
    4 //在文件一开始,就说明了这个文件是当运行级别改变就要更改相关的服务
    //设置终端,将 CR 字符映射为 NL 字符,避免阶梯效应
      stty onlcr 0>&1
      # Get first argument. Set new runlevel to this argument.                      
      [ "$1" != "" ] && runlevel=$1                                                 
      if [ "$runlevel" = "" ]                                                       
      then                                                                          
        echo "Usage: $0 <runlevel>" >&2                                             
        exit 1                                                                      
      fi                                                                            
    //如果没有获取到运行级别就退出
    previous=$PREVLEVEL
      [ "$previous" = "" ] && previous=N
    
        //传入参数是S的话,则$runleve=S $previous=N
      export runlevel previous
    //若$runlevel=“S”,即检查rcS.d是否为目录。
      if [ -d /etc/rc$runlevel.d ]
      then
        //rcS.d是目录
        PROGRESS_STATE=0
    
        //Split the remaining portion of the progress bar into thirds
        progress_size=$(((100 - $PROGRESS_STATE) / 3))//progress_size = 100/3 =33
    
        case "$runlevel" in//runlevel=S
            0|6)
                first_step=-100
                progress_size=100
                step_change=1
                ;;
         S)
                //Begin where the initramfs left off and use 2/3of the remaining space
                first_step=$PROGRESS_STATE ///progress_size = 100/3 =33
                progress_size=$(($progress_size * 2))//progress_size=66
                step_change=1
                ;;
            *)
                //Begin where rcS left off and use the final 1/3 ofthe space (by leaving progress_size unchanged)
                first_step=$(($progress_size * 2 + $PROGRESS_STATE))
                step_change=1
                ;;
        esac
    num_steps=0
        for s in /etc/rc$runlevel.d/[SK]*; //s取/etc/rcS.d目录下以S或K开头的文件名
        do
            //这句话的含义去掉变量s中所有的/etc/rcS.d/S??的部分
            //例:s=/etc/rc$runlevel.d/S10checkroot,那么去掉/etc/rc$runlevel.d/K??部分后,s为checkroot
        case "${s##/etc/rc$runlevel.d/S??}" in
            gdm|xdm|kdm|reboot|halt)//若s剩下的文件名中为这五个则跳出for语句
                break
                ;;
        esac
        num_steps=$(($num_steps + 1))//num_steps递加,表示查找到此目录下/etc/rcS.d有多少个脚本
      done//for语句结束
            step=0    
     # First, run the KILL scripts.       首先运行KILL      
        if [ $previous != N ]                                    //由于previous = N ,所以一下不执行                   
        then                                                                        
            for i in /etc/rc$runlevel.d/K[0-9][0-9]*                                
            do                                                                      
                # Check if the script is there.                                     
                [ ! -f $i ] && continue                                             
                                                                                    
                # Stop the service.                                                 
                startup $i stop                                                     
            done                                                                    
        fi            
                                                                  
        # Now run the START scripts for this runlevel.                              
        for i in /etc/rc$runlevel.d/S*                                              
        do                                                                          
            [ ! -f $i ] && continue                                                 
                                                                                    
            if [ $previous != N ] && [ $previous != S ]     //由于previous为N所以跳过            
            then                                                                    
                #                                                                   
                # Find start script in previous runlevel and                        
                # stop script in this runlevel.                                     
                #                                                                   
                suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]}                          
                stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix                          
                previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix                
                #                                                                   
                # If there is a start script in the previous level                  
                # and _no_ stop script in this level, we don't                      
                # have to re-start the service.                                     
                #                                                                   
                [ -f $previous_start ] && [ ! -f $stop ] && continue                
            fi                                                                      
            case "$runlevel" in                                                     
                0|6)                                                                
                    startup $i stop                                                 
                    ;;                                    
                *)                                                                  
                    startup $i start            //然后启动了相关的服务   运行在文件前面定义的 startup 函数                   
                    ;;                                                              
            esac                                                                    
        done                                                                        
      fi                                                                            

    startup函数有如下定义:

    #                                                                               
    # Start script or program.                                                      
    #                                                                               
    startup() {                                                                     
      # Handle verbosity                                                            
      [ "$VERBOSE" = very ] && echo "INIT: Running $@..."                           
                                                                                    
      case "$1" in             //判断第一个参数,如果是一个脚本,执行第一个                
        *.sh)                                                                       
            # Source shell script for speed.                                        
            (                                                                       
                trap - INT QUIT TSTP                                                
                scriptname=$1                                                       
                shift                               //shift 命令每执行一次,变量的个数($#)减一,而变                    量值提前一位                              
                . $scriptname                  //在执行第一个参数                                     
            )                                                                       
            ;;                                                                      
        *)                            //如果不是一个脚本,那么认为是一个服务                                              
            "$@"                                                                    
            ;;                                                                      
      esac                                                                          
      startup_progress             //再运行前一个函数                                                  
    }                                                                               
                                    

    startup_progress 函数详解

    startup_progress() {                                                            
        step=$(($step + $step_change))                                              
        if [ "$num_steps" != "0" ]; then                                            
            progress=$((($step * $progress_size / $num_steps) + $first_step))       
        else                                                                        
            progress=$progress_size                                                 
        fi                                                                          
        #echo "PROGRESS is $progress $runlevel $first_step + ($step of $num_steps) $step_change $progress_size"
        #if type psplash-write >/dev/null 2>&1; then                                
        #    TMPDIR=/mnt/.psplash psplash-write "PROGRESS $progress" || true        
        #fi                                                                         
        if [ -e /mnt/.psplash/psplash_fifo ]; then                                  
            echo "PROGRESS $progress" > /mnt/.psplash/psplash_fifo                  
        fi                                                                          
        echo progress over...                                                       
    }                                                                               
                                                                    

    最后,执行qt.sh

    #Uncomment to cause psplash to exit manually, otherwise it exits when it sees a VC switch
    if [ "x$runlevel" != "xS" ] && [ ! -x /etc/init.d/xserver-nodm ]; then          
        . /etc/init.d/qt.sh                                                         
    #    if type psplash-write >/dev/null 2>&1; then                                
    #        TMPDIR=/mnt/.psplash psplash-write "QUIT" || true                      
    #       umount /mnt/.psplash                                                    
    #    fi                                                                         
    fi                                                                           

    参考:

    http://www.cnblogs.com/cnland/archive/2013/03/26/2981967.html

    https://wiki.archlinux.org/index.php/Arch_boot_process_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)#Init_.E6.B5.81.E7.A8.8B

    http://blog.chinaunix.net/uid-17188120-id-4073497.html

  • 相关阅读:
    Java课堂测试——一维数组
    05构建之法阅读笔记之二
    第八周个人总结
    团队项目第一篇——NABCD
    第七周学习进度报告
    地铁合作的第二周
    04构建之法阅读笔记之一
    第六周学习进度报告
    03人月神话阅读笔记之三
    地铁合作的第一周
  • 原文地址:https://www.cnblogs.com/chenfulin5/p/5892507.html
Copyright © 2020-2023  润新知