Loading [MathJax]/jax/output/HTML-CSS/jax.js

linux系统启动流程

简介:

POST-->BIOS(Boot Sequence)-->MBR(Bootload,446)-->Kernel-->init


POST:加电自检,通电时cpu会自己找到rom里面的程序进行自检,检查完毕后把控制权转交给BIOS

BIOS:我们的操作系统可以装在各种各样的位置,BIOS里面有个boot Sequence,可以指定介质(u盘、硬盘等)的查找顺序,找到介质里面的MBR并把控制权交给它,(如果找不到介质里面的MBR,则查找下一个介质,如果介质里面的MBR损坏则提示错误信息并停留)

MBR:MBR里面分两部分446字节的Bootload和16字节的分区表,Bootload会根据分区表查找活动分区的Kernel并装载,然后传递控制权

Kernel:Kernel获取控制权后会去探测硬件并挂载等,为实现它的功能(文件系统、进程管理、网络管理、安全功能等)初始化环境,然后生成第一个用户进程init

init:用户空间的第一个进程,id号为1,所有进程的父进程


    我们知道init进程在/sbin,因此,我们必须先识别/sbin所在的分区,我们知道linux的系统分区有些可以单独分区,有些不能。和系统初始化相关的不能单独分区,比如/bin、/sbin,和初始化无关,提供第三方特性的可以单独分区,比如/home,/usr。 这两者都有个共同点,都必须从根开始识别,我们把/所在的文件系统叫做根文件系统。

    内核在设计上有两种设计风格:微内核和单内核。微内核把核心和外围功能分开,需要某些功能的时候再加载对应的子系统,因此有先天性优势,但是这种风格的内核设计逻辑很复杂,对冲了其优势。  单内核把功能和核心做在一起,因此逻辑实现上比较简单。我们知道根文件系统要想使用硬件必须有相对应硬件的驱动程序,但是硬件多种多样,所需的驱动也是各不相同,如果把这些驱动都做进内核,无疑会使内核变得十分的庞大,而我们的硬件设备往往是单一的,因此单内核设计风格上引用了微内核的设计理念,把所需要的驱动等有的做成核心,有的做成模块,内核编译时只选择地编译,这样内核也变得精简了起来。linux是单内核设计风格,系统加载的时候只加载核心,而模块则要到硬盘的 /lib/modules/“内核版本号命名的目录”/ 下去读取,这样核心只有一两兆左右,模块却可以很大。 但是这样也会导致一个问题: 当我们没有把模块所在磁盘的驱动编译进核心时候,我们就会陷入两难,我们要想访问磁盘则需要加载对应的模块,要想加载对应的模块,需要能先访问磁盘。

    为了解决这个问题,linux使用了一个类似中间人角色的文件,这个文件含有对应磁盘的驱动,那这个文件怎么知道需要哪些驱动呢?原因在于这个文件是系统安装的最后由系统安装程序生成的,安装程序能够识别对应的驱动,并根据规则判断系统内核需要动态生成。这个文件在redhat5上叫做ramdisk,在redhat6叫ramfs。


核心,动态加载 内核模块

内核:/lib/modules/“内核版本号命名的目录”/

内核设计风格:

    单内核:linux(LWP)

        核心:ko (Kernel object)    

    微内核:windows,Solaris(线程)

redhat5:ramdisk-->initrd

redhat6:ramfs-->initramfs

chroot:改变/文件系统,切换的路径里面需要包含二进制程序和所依赖的库文件

     chroot [OPTION] NEWROOT [COMMAND [ARG]...]

ldd /PATH/TO/BINARY_FILE  :判断一个二进制程序所需要的库


linux的运行级别:0-6

    0:halt

    1:single user mode

    2:multi user mode,no nfs

    3:multi user mode ,text

    4:reserved

    5:multi user mode,graphic mode

    6:reboot


使用initrd的系统启动过程如下:

post-->bios-->mbr-->kernel-->initrd-->init


MBR(bootloader):

    bootloader有各种各样工具,比较常见的有lilo和grub

        lilo:LInux LOader  不能识别1024柱面以后的数据,所以不支持大硬盘,在嵌入式中比较常用

        Grub:GRand Unified Bootloader

            Stage1:MBR

            Stage1.5:识别文件系统

            Stage2:/boot/grub/ 引导内核,并转交控制权


    grub工作过程分成两部分,stage1 在MBR中,作用在于查找并引导至stage2,这样使得MBR的bootload不再限制于446字节,当grub的stage1阶段无法识别stage所在磁盘的文件系统时候,就会衍生出stage1.5,stage1.5的作用就是加载stage2所在磁盘的文件系统驱动,使得grub具有读取数据的能力(这个也是为什么grub可以加载内核,内核却不可以加载根的原因,内核被加载到内存中的时候,内核如果本身没有识别根文件系统所在磁盘的驱动,那么它就无法加载文件系统,也就是需要initrd这个软件来过渡,,识别需要两个必要条件:1 磁盘的驱动, 2 文件系统的驱动 )


grub.conf 解释:

default=0   #多个title的默认选项,第一个为0

timeout=5   #用户选择的超时时间

splashimage=(hd0,0)/grub/splash.xpm.gz #设置背景图片

hiddenmenu #是否隐藏菜单,隐藏开机则需额外按键才能显示

title CentOS 6 (2.6.32-573.el6.x86_64)  #标题,可自定义

root (hd0,0)    #根文件系统所在位置,这里跟linux不一样,不管是ide口还是其他硬盘都识别为hd# 0代表第几个分区

kernel /vmlinuz-2.6.32-573.el6.x86_64 ro root=UUID=b670d3c5-487a-43be-9624-5ad90ffda293 rd_NO_LUKS rd_NO_LVM LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet   #内核所在位置及其参数,注意:如果这里的boot是单独分区,那么内核所在位置就是/vmlinuzXXX ,如果boot没有单独分区那么内核的位置就是 /PATH/TO/boot/vmlinzxxx

initrd /initramfs-2.6.32-573.el6.x86_64.img  #initrd的位置,同上

        

password --md5  xxxxxxxxxx  #选项的加密,启用后需要输入密码才能访问,密码可以由grub-md5-crypt命令生成,也可以不加--md5 明文存放,放在title前面表示编辑grub引导需要密码,放在title里面表示想要引导此内核需要密码。


查看运行级别:

runlevel

who -r


安装grub stage1的两种方法:

第一种:

#grub

grub> root (hd0,0)

grub>setup (hd0)

第二种:

grub-install --root-directory=/PATH/TO/boot's_father_dir


在grub命令行中引导系统:

grub> find (hd#,N)/        tab键可以查看该路径下的文件

grub>root (hd#,N)

grub> kernel  /PATH/TO/KERNEL_FILE

grub>initrd   /PATH/TO/INITRD_FILE

grub>boot


kernel初始化的过程:

1,设备探测

2,驱动初始化(可能会用到initrd)

3,以只读挂载根文件系统

4,装载第一个进程init(PID 1)


init进程的配置文件/etc/inittab

格式: id:runlevel:action:process

id:标识符

runlevel:在哪个运行等级下执行此行

action:在什么情况下运行此行

process:要运行的程序


ACTION:

    initdefault:设定默认运行级别

    sysinit:系统初始化

    wait:等待级别切换至次级别时运行

    respawn:一旦程序终止,会重新启动

    

/etc/inittab完成的任务:

  1. 设置系统运行级别

  2. 执行系统初始化脚本

  3. 执行对应级别的服务脚本

  4. 定义:ctrl-alt-del按键执行程序

  5. ups电源断电/中途来电执行的操作

  6. 启动虚拟终端

启动图形终端

 

/etc/inittab执行的系统开机启动sysV风格脚本特点:

  1. 都在/etc/init.d/目录下

  2. 脚本必须至少支持四种传递参数[start|stop|restar|status]

  3. 在各个级别的链接中,K开头的服务会stop,S开头的服务会start

  4. 要想自动在每个运行级别中用chkconfig自动创建链接,注释行必须含有chkconfig和description


sysV脚本中的chkconfig注释行格式:

#chkconfig: runlevel SS KK 

例子:chkconfig: 2345 08 92

    runlevel代表在哪些运行级别中启动脚本

    SS代表/etc/rc#.d/下 S 开头后面跟的序号,比如本例/etc/rc3.d/S08iptables,SS代表08

    KK则代表K后面的序号,一般SS+KK=99 左右,这是为了遵循先启动的后关闭原则(因为先启动的可能被后面的服务依赖)


chkconfig 命令:

       chkconfig --list [name]

       chkconfig --add name

       chkconfig --del name

       chkconfig [--level levels] name <on|off|reset|resetpriorities>

       chkconfig [--level levels] name

 name代表/etc/init.d/下的服务名字

 level表示在哪些级别下运行,可省略,默认2345


一个特殊的文件:/etc/rc.local 这个是系统启动最后执行的脚本,在各个级别中的链接都是S99,所以一些想要开机执行的命令可以写入到这里


守护进程类型:

    独立守护进程:进程的启动关闭都由进程自己管理,类似于以上服务脚本

    瞬时守护进程:一个进程管理多个服务,服务启动与否取决于管理进程,适用于平时很少访问量的服务,这个管理进程在centos中就是xinetd,扮演类似代理人角色


一个sysV风格脚本案例:

#!/bin/bash

#

#chkconfig: 2345 22 77

#description: edit by linzb.

#

LOCK_FILE=/var/lock/subsys/myservice

Usage(){

echo "`basename $0 ` [start|stop|status|restart]"

}

start(){

touch $LOCK_FILE

echo "starting.."

}

stop(){

rm -f  LOCKFILE> /dev/null

echo "stoping.."

}

status(){

if [ -f $LOCK_FILE ];then

echo "running.."

else

echo "stopped"

fi

}

case $1 in

start)

start;;

stop)

stop;;

restart)

stop

start;;

status)

status;;

*)

Usage;;

esac



注:/var/lock/subsys/这个目录下经常放服务的锁文件,很多服务根据这里面的文件判断服务是否启动

    











本文转自biao007h51CTO博客,原文链接:http://blog.51cto.com/linzb/1790459 ,如需转载请自行联系原作者



相关文章
Linux系统资源管理:多角度查看内存使用情况。
要知道,透过内存管理的窗口,我们可以洞察到Linux系统运行的真实身姿,如同解剖学家透过微观镜,洞察生命的奥秘。记住,不要惧怕那些高深的命令和参数,他们只是你掌握系统"魔法棒"的钥匙,熟练掌握后,你就可以骄傲地说:Linux,我来了!
67 27
|
8天前
|
Linux系统ext4磁盘扩容实践指南
这个过程就像是给你的房子建一个新的储物间。你需要先找到空地(创建新的分区),然后建造储物间(格式化为ext4文件系统),最后将储物间添加到你的房子中(将新的分区添加到文件系统中)。完成这些步骤后,你就有了一个更大的储物空间。
57 10
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
2月前
|
Linux系统之whereis命令的基本使用
Linux系统之whereis命令的基本使用
103 24
Linux系统之whereis命令的基本使用
|
20天前
|
Linux系统中如何查看CPU信息
本文介绍了查看CPU核心信息的方法,包括使用`lscpu`命令和读取`/proc/cpuinfo`文件。`lscpu`能快速提供逻辑CPU数量、物理核心数、插槽数等基本信息;而`/proc/cpuinfo`则包含更详细的配置数据,如核心ID和处理器编号。此外,还介绍了如何通过`lscpu`和`dmidecode`命令获取CPU型号、制造商及序列号,并解释了CPU频率与缓存大小的相关信息。最后,详细解析了`lscpu`命令输出的各项参数含义,帮助用户更好地理解CPU的具体配置。
59 8
深度体验阿里云系统控制台:SysOM 让 Linux 服务器监控变得如此简单
作为一名经历过无数个凌晨三点被服务器报警电话惊醒的运维工程师,我对监控工具有着近乎苛刻的要求。记得去年那次大型活动,我们的主站流量暴增,服务器内存莫名其妙地飙升到90%以上,却找不到原因。如果当时有一款像阿里云 SysOM 这样直观的监控工具,也许我就不用熬通宵排查问题了。今天,我想分享一下我使用 SysOM 的亲身体验,特别是它那令人印象深刻的内存诊断功能。
|
10天前
|
微服务2——MongoDB单机部署4——Linux系统中的安装启动和连接
本节主要介绍了在Linux系统中安装、启动和连接MongoDB的详细步骤。首先从官网下载MongoDB压缩包并解压至指定目录,接着创建数据和日志存储目录,并配置`mongod.conf`文件以设定日志路径、数据存储路径及绑定IP等参数。之后通过配置文件启动MongoDB服务,并使用`mongo`命令或Compass工具进行连接测试。此外,还提供了防火墙配置建议以及服务停止的两种方法:快速关闭(直接杀死进程)和标准关闭(通过客户端命令安全关闭)。最后补充了数据损坏时的修复操作,确保数据库的稳定运行。
41 0
|
4月前
|
Linux缓存管理:如何安全地清理系统缓存
在Linux系统中,内存管理至关重要。本文详细介绍了如何安全地清理系统缓存,特别是通过使用`/proc/sys/vm/drop_caches`接口。内容包括清理缓存的原因、步骤、注意事项和最佳实践,帮助你在必要时优化系统性能。
337 78
Linux系统查看操作系统版本信息、CPU信息、模块信息
在Linux系统中,常用命令可帮助用户查看操作系统版本、CPU信息和模块信息
205 23
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
156 13