Linux启动过程

Linux启动过程

前言:

  Linux是一种自由和开放源代码的类UNIX操作系统。该操作系统的内核由林纳斯·托瓦兹在1991年10月5日首次发布。在加上用户空间的应用程序之后,成为Linux操作系统。Linux是自由软件和开放源代码软件发展中最著名的例子。

  接触Linux的时间也不算短了,一直都是直接使用Linux操作系统进行一些工作,很少去了解系统从开机到能使用的整个过程,感觉有需要好好理解下整个系统的启动过程,故写这篇博客加深一下理解。

 

先通过一张图来简单了解下整个系统启动的流程,整个过程基本可以分为POST-->BIOS-->MBR(GRUB)-->Kernel-->Init-->Runlevel。下面会详细说明每个过程的作用。

图1-1:系统启动流程

BIOS

  BIOS(Basic Input/Output System),基本输入输出系统,该系统存储于主板的ROM芯片上,计算机在开机时,会最先读取该系统,然后会有一个加电自检过程,这个过程其实就是检查CPU和内存,计算机最基本的组成单元(控制器、运算器和存储器),还会检查其他硬件,若没有异常就开始加载BIOS程序到内存当中。详细的BIOS功能,这边就不说了,BIOS主要的一个功能就是存储了磁盘的启动顺序,BIOS会按照启动顺序去查找第一个磁盘头的MBR信息,并加载和执行MBR中的Bootloader程序,若第一个磁盘不存在MBR,则会继续查找第二个磁盘(PS:启动顺序可以在BIOS的界面中进行设置),一旦BootLoader程序被检测并加载内存中,BIOS就将控制权交接给了BootLoader程序。

 

MBR

  MBR(Master Boot Record),主引导记录,MBR存储于磁盘的头部,大小为512bytes,其中,446bytes用于存储BootLoader程序,64bytes用于存储分区表信息,最后2bytes用于MBR的有效性检查。

 

GRUB

  GRUB(Grand Unified Bootloader),多系统启动程序,其执行过程可分为三个步骤:

    Stage1:这个其实就是MBR,它的主要工作就是查找并加载第二段Bootloader程序(stage2),但系统在没启动时,MBR根本找不到文件系统,也就找不到stage2所存放的位置,因此,就有了stage1_5

    Stage1_5:该步骤就是为了识别文件系统

    Stage2:GRUB程序会根据/boot/grub/grub.conf文件查找Kernel的信息,然后开始加载Kernel程序,当Kernel程序被检测并在加载到内存中,GRUB就将控制权交接给了Kernel程序。

    PS:实际上这个步骤/boot还没被挂载,GRUB直接识别grub所在磁盘的文件系统,所以实际上应该是/grub/grub.conf文件,该配置文件的信息如下:

    grub.conf: 

    #boot=/dev/sda

    default=0        #设定默认启动的title的编号,从0开始

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

    splashimage=(hd0,0)/boot/grub/splash.xpm.gz    #GRUB的背景图片

    hiddenmenu     #隐藏菜单

    title CentOS (2.6.18-194.el5PAE)      #内核标题

        root (hd0,0)         #内核文件所在的设备

        kernel /vmlinuz-2.6.18-194.el5PAE ro root=LABEL=/     #内核文件路径以及传递给内核的参数

        initrd /initrd-2.6.18-194.el5PAE.img                            #ramdisk文件路径

 

 

 Kernel

  Kernel,内核,Kernel是Linux系统最主要的程序,实际上,Kernel的文件很小,只保留了最基本的模块,并以压缩的文件形式存储在硬盘中,当GRUB将Kernel读进内存,内存开始解压缩内核文件。讲内核启动,应该先讲下initrd这个文件,

  initrd(Initial RAM Disk),它在stage2这个步骤就被拷贝到了内存中,这个文件是在安装系统时产生的,是一个临时的根文件系统(rootfs)。因为Kernel为了精简,只保留了最基本的模块,因此,Kernel上并没有各种硬件的驱动程序,也就无法识rootfs所在的设备,故产生了initrd这个文件,该文件装载了必要的驱动模块,当Kernel启动时,可以从initrd文件中装载驱动模块,直到挂载真正的rootfs,然后将initrd从内存中移除。

  Kernel会以只读方式挂载根文件系统,当根文件系统被挂载后,开始装载第一个进程(用户空间的进程),执行/sbin/init,之后就将控制权交接给了init程序。

 

Init

  init,初始化,顾名思义,该程序就是进行OS初始化操作,实际上是根据/etc/inittab(定义了系统默认运行级别)设定的动作进行脚本的执行,第一个被执行的脚本为/etc/rc.d/rc.sysinit,这个是真正的OS初始化脚本,简单讲下这个脚本的任务(可以去看看实际脚本,看看都做了什么):

  1、激活udev和selinux;2、根据/etc/sysctl.conf文件,来设定内核参数;3、设定系统时钟;4、装载硬盘映射;5、启用交换分区;6、设置主机名;7、根文件系统检测,并以读写方式重新挂载根文件系统;8、激活RAID和LVM设备;9、启用磁盘配额;10、根据/etc/fstab,检查并挂载其他文件系统;11、清理过期的锁和PID文件

  执行完后,根据配置的启动级别,执行对应目录底下的脚本,最后执行/etc/rc.d/rc.local这个脚本,至此,系统启动完成。

  

Runlevel

  runlevel,运行级别,不同的级别会启动的服务不一样,init会根据定义的级别去执行相应目录下的脚本,Linux的启动级别分为以下几种

  0:关机模式

  1:单一用户模式(直接以管理员身份进入)

  2:多用户模式(无网络)

  3:多用户模式(命令行)

  4:保留

  5:多用户模式(图形界面)

  6:重启

 

  在不同的运行级别下,/etc/rc.d/rc这个脚本会分别执行不同目录下的脚本

  • Run level 0 – /etc/rc.d/rc0.d/
  • Run level 1 – /etc/rc.d/rc1.d/
  • Run level 2 – /etc/rc.d/rc2.d/
  • Run level 3 – /etc/rc.d/rc3.d/
  • Run level 4 – /etc/rc.d/rc4.d/
  • Run level 5 – /etc/rc.d/rc5.d/
  • Run level 6 – /etc/rc.d/rc6.d/

  这些目录下的脚本只有K*和S*开头的文件,K开头的文件为开机需要执行关闭的服务,S开头的文件为开机需要执行开启的服务。

https://www.cnblogs.com/changxr/p/8023341.html

 

Active_Code

年华易逝不及鸿鹄之志 无顾浮层充实人间烟火 莫饮天涯断肠干将进酒 却怎琵琶犹抱醉翁亭意

linux系统的启动过程简要分析

接触linux系统运维已经好几年了,常常被问到linux系统启动流程问题,刚好今天有空来梳理下这个过程:
一般来说,所有的操作系统的启动流程基本就是:

总的来说,linux系统启动流程可以简单总结为以下几步:
1)开机BIOS自检,加载硬盘。
2)读取MBR,进行MBR引导。
3)grub引导菜单(Boot Loader)。
4)加载内核kernel。
5)启动init进程,依据inittab文件设定运行级别
6)init进程,执行rc.sysinit文件。
7)启动内核模块,执行不同级别的脚本程序。
8)执行/etc/rc.d/rc.local
9)启动mingetty,进入系统登陆界面。

linux系统安装时,如果要想设置开启启动项,可以:
开机到BIOS提醒界面,按键F11(Dell服务器的做法)进入BIOS设置BOOT MENU,继而设置启动项:硬盘HD启动,光盘CD/DVD启动,还是U盘USB启动。

下面就linux操作系统的启动过程做一详细解析记录:

加载内核
操作系统接管硬件以后,首先读入 /boot 目录下的内核文件。

1

2

3

4

5

6

7

8

9

10

[root@bastion-IDC ~]# ll /boot/

total 21668

-rw-r--r--. 1 root root   105195 Nov 22  2013 config-2.6.32-431.el6.x86_64

drwxr-xr-x. 3 root root     1024 Aug 22 16:31 efi

drwxr-xr-x. 2 root root     1024 Aug 22 16:32 grub

-rw-------. 1 root root 15217153 Aug 22 16:32 initramfs-2.6.32-431.el6.x86_64.img

drwx------. 2 root root    12288 Aug 22 16:24 lost+found

-rw-r--r--. 1 root root   193758 Nov 22  2013 symvers-2.6.32-431.el6.x86_64.gz

-rw-r--r--. 1 root root  2518236 Nov 22  2013 System.map-2.6.32-431.el6.x86_64

-rwxr-xr-x. 1 root root  4128368 Nov 22  2013 vmlinuz-2.6.32-431.el6.x86_64

启动初始化进程
内核文件加载以后,就开始运行第一个程序 /sbin/init,它的作用是初始化系统环境。

由于init是第一个运行的程序,它的进程编号(pid)就是1。其他所有进程都从它衍生,都是它的子进程。

确定运行级别
许多程序需要开机启动。它们在Windows叫做"服务"(service),在Linux就叫做"守护进程"(daemon)。
init进程的一大任务,就是去运行这些开机启动的程序。但是,不同的场合需要启动不同的程序,比如用作服务器时,需要启动Apache,用作桌面就不需要。Linux允许为不同的场合,分配不同的开机启动程序,这就叫做"运行级别"(runlevel)。也就是说,启动时根据"运行级别",确定要运行哪些程序。

Linux预置七种init运行级别(0-6):
0:关机模式    (相当于poweroff)
1:单用户模式(破解root密码)
2:无网络支持的多用户模式
3:有网络支持的多用户模式(也就是文本模式,工作中最常用的模式)
4:保留,未使用
5:有网络支持的X-windows支持多用户模式(也就是桌面图形模式)
6: 重新引导系统,即重启    (相当于reboot)

init进程首先读取文件 /etc/inittab,它是运行级别的设置文件。
如果打开它,可以看到第一行是这样的:
[root@bastion-IDC ~]# cat /etc/inittab 
....
id:3:initdefault:

initdefault的值是3,表明系统启动时的运行级别为3。如果需要指定其他级别,可以手动修改这个值。
那么,运行级别3有哪些什么程序呢,系统怎么知道每个级别应该加载哪些程序呢?
答案是每个运行级别在/etc目录下面,都有一个对应的子目录,指定要加载的程序。

  /etc/rc0.d
  /etc/rc1.d
  /etc/rc2.d
  /etc/rc3.d
  /etc/rc4.d
  /etc/rc5.d
  /etc/rc6.d

上面目录名中的"rc",表示run command(运行程序),最后的d表示directory(目录)。下面让我们看看 /etc/rc3.d 目录中到底指定了哪些程序。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

[root@bastion-IDC ~]# ll /etc/rc3.d/

total 0

lrwxrwxrwx. 1 root root 19 Aug 22 16:30 K10saslauthd -> ../init.d/saslauthd

lrwxrwxrwx. 1 root root 18 Aug 22 16:47 K15svnserve -> ../init.d/svnserve

lrwxrwxrwx. 1 root root 15 Aug 23 16:21 K25squid -> ../init.d/squid

lrwxrwxrwx. 1 root root 19 Dec 23 13:14 K45memcached -> ../init.d/memcached

lrwxrwxrwx. 1 root root 20 Aug 22 16:30 K50netconsole -> ../init.d/netconsole

lrwxrwxrwx. 1 root root 13 Dec 21 17:45 K60nfs -> ../init.d/nfs

lrwxrwxrwx. 1 root root 20 Dec 21 17:45 K69rpcsvcgssd -> ../init.d/rpcsvcgssd

lrwxrwxrwx. 1 root root 17 Nov 24 14:45 K75ntpdate -> ../init.d/ntpdate

lrwxrwxrwx. 1 root root 20 Aug 22 16:31 K87multipathd -> ../init.d/multipathd

lrwxrwxrwx. 1 root root 21 Aug 22 16:30 K87restorecond -> ../init.d/restorecond

lrwxrwxrwx. 1 root root 15 Aug 22 16:30 K89rdisc -> ../init.d/rdisc

lrwxrwxrwx. 1 root root 22 Aug 22 16:31 S02lvm2-monitor -> ../init.d/lvm2-monitor

lrwxrwxrwx. 1 root root 16 Aug 22 16:31 S07iscsid -> ../init.d/iscsid

lrwxrwxrwx. 1 root root 19 Aug 22 16:30 S08ip6tables -> ../init.d/ip6tables

lrwxrwxrwx. 1 root root 18 Aug 22 16:30 S08iptables -> ../init.d/iptables

lrwxrwxrwx. 1 root root 17 Aug 22 16:30 S10network -> ../init.d/network

lrwxrwxrwx. 1 root root 16 Aug 22 16:31 S11auditd -> ../init.d/auditd

lrwxrwxrwx. 1 root root 17 Aug 22 16:30 S12rsyslog -> ../init.d/rsyslog

lrwxrwxrwx. 1 root root 15 Dec 21 17:45 S13iscsi -> ../init.d/iscsi

lrwxrwxrwx. 1 root root 17 Dec 21 17:45 S13rpcbind -> ../init.d/rpcbind

lrwxrwxrwx. 1 root root 17 Dec 21 17:45 S14nfslock -> ../init.d/nfslock

lrwxrwxrwx. 1 root root 19 Aug 22 16:31 S15mdmonitor -> ../init.d/mdmonitor

lrwxrwxrwx. 1 root root 17 Dec 21 17:45 S19rpcgssd -> ../init.d/rpcgssd

lrwxrwxrwx. 1 root root 26 Aug 22 16:31 S25blk-availability -> ../init.d/blk-availability

lrwxrwxrwx. 1 root root 15 Aug 22 16:30 S25netfs -> ../init.d/netfs

lrwxrwxrwx. 1 root root 19 Aug 22 16:30 S26udev-post -> ../init.d/udev-post

lrwxrwxrwx. 1 root root 18 Oct 25 11:49 S50onealert -> ../init.d/onealert

lrwxrwxrwx. 1 root root 14 Aug 22 16:31 S55sshd -> ../init.d/sshd

lrwxrwxrwx. 1 root root 16 Oct 26 09:47 S56xinetd -> ../init.d/xinetd

lrwxrwxrwx. 1 root root 17 Aug 22 16:30 S80postfix -> ../init.d/postfix

lrwxrwxrwx. 1 root root 15 Aug 22 16:30 S90crond -> ../init.d/crond

lrwxrwxrwx. 1 root root 11 Aug 22 16:30 S99local -> ../rc.local

可以看到:
字母S表示Start,也就是启动的意思(启动脚本的运行参数为start)
如果这个位置是字母K,就代表Kill(关闭),即如果从其他运行级别切换过来,需要关闭的程序(启动脚本的运行参数为stop)。
后面的两位数字表示处理顺序,数字越小越早处理,所以第一个启动的程序是motd,然后是rpcbing、nfs......数字相同时,则按照程序名的字母顺序启动,所以rsyslog会先于sudo启动。
这个目录里的所有文件(除了README),就是启动时要加载的程序。如果想增加或删除某些程序,不建议手动修改 /etc/rcN.d 目录,最好是用一些专门命令进行管理(参考这里和这里)。

加载开机启动程序
前面提到,七种预设的"运行级别"各自有一个目录,存放需要开机启动的程序。不难想到,如果多个"运行级别"需要启动同一个程序,那么这个程序的启动脚本,就会在每一个目录里都有一个拷贝。这样会造成管理上的困扰:如果要修改启动脚本,岂不是每个目录都要改一遍?
Linux的解决办法,就是七个 /etc/rcN.d 目录里列出的程序,都设为链接文件,指向另外一个目录 /etc/init.d ,真正的启动脚本都统一放在这个目录中。init进程逐一加载开机启动程序,其实就是运行这个目录里的启动脚本。

下面就是链接文件真正的指向

1

2

[root@bastion-IDC ~]# ls -l /etc/rc3.d

lrwxrwxrwx. 1 root root 10 Aug 22 16:30 /etc/rc3.d -> rc.d/rc3.d

这样做的另一个好处,就是如果你要手动关闭或重启某个进程,直接到目录 /etc/init.d 中寻找启动脚本即可。
比如,我要重启iptables服务器,就运行下面的命令:
[root@bastion-IDC ~]# /etc/init.d/iptables restart

/etc/init.d 这个目录名最后一个字母d,是directory的意思,表示这是一个目录,用来与程序 /etc/init 区分。

用户登录
开机启动程序加载完毕以后,就要让用户登录了。

一般来说,用户的登录方式有三种:命令行登录、ssh登录、图形界面登录。这三种情况,都有自己的方式对用户进行认证。
1)命令行登录:init进程调用getty程序(意为get teletype),让用户输入用户名和密码。输入完成后,再调用login程序,核对密码(Debian还会再多运行一个身份核对程序/etc/pam.d/login)。如果密码正确,就从文件 /etc/passwd 读取该用户指定的shell,然后启动这个shell。
2)ssh登录:这时系统调用sshd程序(Debian还会再运行/etc/pam.d/ssh ),取代getty和login,然后启动shell。
3)图形界面登录:init进程调用显示管理器,Gnome图形界面对应的显示管理器为gdm(GNOME Display Manager),然后用户输入用户名和密码。如果密码正确,就读取/etc/gdm3/Xsession,启动用户的会话。

进入 login shell
所谓shell,简单说就是命令行界面,让用户可以直接与操作系统对话。用户登录时打开的shell,就叫做login shell。

Linuix默认的shell是Bash,它会读入一系列的配置文件。上一步的三种情况,在这一步的处理,也存在差异。
1)命令行登录:首先读入 /etc/profile,这是对所有用户都有效的配置;然后依次寻找下面三个文件,这是针对当前用户的配置。
  ~/.bash_profile
  ~/.bash_login
  ~/.profile
需要注意的是,这三个文件只要有一个存在,就不再读入后面的文件了。比如,要是 ~/.bash_profile 存在,就不会再读入后面两个文件了。
2)ssh登录:与第一种情况完全相同。
3)图形界面登录:只加载 /etc/profile 和 ~/.profile。也就是说,~/.bash_profile 不管有没有,都不会运行。

打开 non-login shell
老实说,上一步完成以后,Linux的启动过程就算结束了,用户已经可以看到命令行提示符或者图形界面了。但是,为了内容的完整,必须再介绍一下这一步。
用户进入操作系统以后,常常会再手动开启一个shell。这个shell就叫做 non-login shell,意思是它不同于登录时出现的那个shell,不读取/etc/profile和.profile等配置文件。

non-login shell的重要性,不仅在于它是用户最常接触的那个shell,还在于它会读入用户自己的bash配置文件 ~/.bashrc。大多数时候,我们对于bash的定制,都是写在这个文件里面的。
你也许会问,要是不进入 non-login shell,岂不是.bashrc就不会运行了,因此bash 也就不能完成定制了?事实上,Debian已经考虑到这个问题了,请打开文件 ~/.profile,可以看到下面的代码:
  if [ -n "BASHVERSION"];then    if[−f"BASHVERSION"];then    if[−f"HOME/.bashrc" ]; then
      . "HOME/.bashrc"    fi  fi  上面代码先判断变量HOME/.bashrc"    fi  fi  上面代码先判断变量BASH_VERSION 是否有值,然后判断主目录下是否存在 .bashrc 文件,如果存在就运行该文件。第三行开头的那个点,是source命令的简写形式,表示运行某个文件,写成"source ~/.bashrc"也是可以的。
因此,只要运行~/.profile文件,~/.bashrc文件就会连带运行。但是上一节的第一种情况提到过,如果存在~/.bash_profile文件,那么有可能不会运行~/.profile文件。解决这个问题很简单,把下面代码写入.bash_profile就行了。
  if [ -f ~/.profile ]; then
    . ~/.profile
  fi
 
这样一来,不管是哪种情况,.bashrc都会执行,用户的设置可以放心地都写入这个文件了。
Bash的设置之所以如此繁琐,是由于历史原因造成的。早期的时候,计算机运行速度很慢,载入配置文件需要很长时间,Bash的作者只好把配置文件分成了几个部分,阶段性载入。系统的通用设置放在 /etc/profile,用户个人的、需要被所有子进程继承的设置放在.profile,不需要被继承的设置放在.bashrc。
顺便提一下,除了Linux以外, Mac OS X 使用的shell也是Bash。但是,它只加载.bash_profile,然后在.bash_profile里面调用.bashrc。而且,不管是ssh登录,还是在图形界面里启动shell窗口,都是如此。

https://www.cnblogs.com/activecode/p/9454472.html

 

Linux 启动过程详解

目录

 
 

1. Linux启动过程

Linux的启动过程是在执行多级初始化过程中启动一个Linux的安装,它在许多方面类似于BSD和其他Unix风格的引导过程,从中衍生出来。

 

引导Linux安装设计多个阶段和软件组成,包括固件初始化,引导加载程序的执行,Linux内核映像的加载和启动,以及各种脚本和守护程序的执行,对于这些阶段和组件中的每一个,存在不同的变化和方法,例如:GRUBLILOSYSLINUXLoadin可用做引导加载程序,而启动脚本可以是传统的init风格,也可以通过现在的方法代替(如systemdupstart

 
 


 
 

2. 启动过程概述

Linux启动过程的早期阶段很大程度取决于计算机体系结构,IBM PC兼容硬件是Linux常用的一种架构,在这些系统上,BIOS起着很重要的作用,可能在其他系统上没有精确的类似物,在以下示例中,假设使用与IBM PC兼容的硬件:

 

  1. BIOS执行特定于实际硬件平台的启动任务,一旦枚举硬件并正确初始化引导所需的硬件,BIOS就会从配置的引导设备加载并执行引导代码。
  2. 引导加载程序通常向用户提供一个可能的引导选项菜单,并有一个默认选项,该选项在经过一段时间后被选中,一旦做出选择,引导加载程序就会将内核加载到内存中,并为其提供一些参数,并赋予其控制权。
  3. 内核如果被压缩,将自动解压缩,然后,它设置系统功能,如基本硬件和内存分页,并掉调用start_kernel(),它执行大部分系统设置(中断、内存管理和其余部分、设备和驱动程序初始化等),然后它分别启动空闲进程、调度程序和init进程,这些进程在用户空间执行。
  4. initshell(susv,bsd,runit)执行的脚本或二进制组件(systemd,upstart)执行的配置文件组成,init具有特定的级别(sysv,bsd)或目标(systemd),每个级别都由特定的服务集(守护进程)组成,它们提供何种非操作系统服务和结构,并形成用户环境,典型的服务器环境启动Web服务器、数据库服务和网络
  5. 典型的桌面环境以一和名为display manager的守护程序开始,该守护程序启动一个图形环境,该图形环境由一个提供图形堆栈的图形服务器和一个提供输入凭据和选择会话的登陆管理器组成, 会话是一组程序,例如UI元素(页面、桌面、小程序等),这些元素可以一起构成一个完整的桌面环境。

 
 


 
 

3. 引导加载阶段

引导加载程序阶段因计算机体系结构而异,由于早期阶段并非特定与操作系统,所以在实际模式下执行主引导记录(MBR)代码并加载第一阶段引导加载程序时,将考虑启动x86x86-64体系结构的基于BIOS的引导过程,在UEFI系统中,可以直接执行负载,比如Linux内核,因此,不需要引导加载程序,下面是一些流行的引导加载程序的摘要:

 

  • GRUB 1 - 包括在运行时读取公共文件系统以访问其配置文件的逻辑,这使GRUB 1能够从文件系统读取配置文件,而不是将其嵌入到MBR中,这允许它在运行时配置并以人类可读的格式指定磁盘和分区而不是依赖于偏移量,它还包含一个命令接口,如果GRUB配置错误或损坏,它可以更容易地修复和修改GRUB
  • GRUB 2 - 不同于GRUB 1,它有两个(可选三个)阶段,能够自动检测各种操作系统和自动配置,第一阶段加载程序(stage 1)由BIOS从主引导记录(MBR)加载和执行,或者由分区引导扇区的另一个引导加载程序加载和执行,它的工作是发现和访问各种文件系统,稍后可以从这些文件系统读取配置,可选的中间阶段加载器(stage 1.5)由第一阶段加载器加载执行,以防第二阶段加载器不是连续的,或者文件系统或硬件需要特殊处理才能访问第二阶段加载器,第二阶段加载器(stage 2)最后加载,并显示GRUB启动菜单,允许用户选择操作系统或检查和编辑启动参数,选择菜单项并给出可选参数后,GRUB将内核加载到内存并将控制权递给它,GRUB 2还能够链式加载另一个引导加载程序

 
 


 
 

4. 内核阶段

 

Linux内核处理所有操作系统进程,例如内存管理、任务调度、I/O、进程间通信和整个系统控制,它分两个阶段加载,在第一阶段,内核(作为压缩的镜像文件)被夹在到内存中并解压缩,然后设置一些基本功能,如基本内存管理,然后最后一次将控件切换到主内核和启动进程,一旦内核完全运行并且作为启动的一部分,在加载和执行之后,内核寻找要运行的init进程,它(单独地)设置用户空间和用户环境和最终登陆所需的进程,然后,内核本身被允许空闲,这取决来自其他进程的调用。

 

4.1 内核加载阶段

内核通常以镜像文件的形式加载,用zlib压缩成zlmage或bzImage格式,它头部的一个例程执行少量的硬件设置,将镜像完全解压到内存中,并在配置时记录任何RAM磁盘,然后,它同通过 /arch/ie86/boot/head和startup_32()(用于基于x86的处理器)进程执行内核启动

 

 

4.2 内核启动阶段

内核的启动函数(也称为swapper或进程0)建立内存管理(分页表和内存分页),检测CPU的类型和任何附加功能,比如浮点数功能,然后通过调用start_kernel()切换到非体系结构特定的Linux内核功能

 

start_kernel执行各种初始化函数,他设置中断处理(IRQ),进一步配置内存,启动init进程(第一个用户空间进程),然后同故宫cpu_idle()启动空闲任务,值得注意的是,内核启动进程还挂载了初始RAM磁盘("initrd"),该磁盘先前在引导阶段作为临时根文件系统加载,initrd允许直接从内存加载驱动程序模块,而不依赖其他设置(例如硬盘)和访问它们所需的驱动程序(例如SATA驱动程序),静态编译到内核中的一些驱动程序和initrd加载的其他驱动程序的这种分割允许使用更小的内核,稍后,通过调用pivot_root()切换根文件系统,该调用将卸载临时根文件系统,并在访问实际根文件系统之后使用实际根文件系统替换它,然后收回临时根文件系统使用的内存。

 

因此,内核初始化设备,将引导加载程序指定的根文件系统安装为只读,并运行Init(/sbin/init),它被指定为系统运行的第一个进程(PID=1),内核在安装文件系统时打印消息,它还可以选择性地运行initrd,以允许在安装根文件系统之前处理安装和设备相关的问题(RAM磁盘之类的)

 

 

Red Had认为,这一阶段的具体内核过程总结如下:

当内核加载时,它立即初始化和配置计算机的内存,并配置附加到系统上的各种硬件,包括所有处理器,I/O子系统和存储设备,然后,它在内存中预定的位置查找压缩后的initrd镜像,对其进行解压、挂载并加载所有必要的驱动程序,接下来,在卸载initrd磁盘镜像并释放磁盘镜像占用的所有内存之前,初始化于文件系统相关的虚拟设备,比如LVM或者RAID,然后内核创建一个根分区,以只读方式挂载根分区,并释放任何未使用的内存,此时,内核被加载到内存中并可运行,然后,由于没有用户应用程序允许对系统进行有意义的输入,因此无法对其进行太多操作,initramfs风格的引导与之类似,但与所表述的initrd引导不同。

 

此时,启动中断后,调度器可以控制系统的总体管理,提供抢占式的多任务处理,而init进程将继续在用户空间引导用户环境。

 
 


 
 

5. 早期的用户空间

initramfs,也成为早期用户空间,从Linux内核2.5.26版本开始就提供了,其目的是替换以前内核在启动过程中执行的尽可能更多的功能,早期用户空间的典型用途是检测需要哪些设备驱动程序来加载主用户空间文件系统从临时文件系统加载它们。

 
 


 
 

6. 初始化过程

 
 

6.1 SysV init

init是系统中所有进程的父进程,由内核执行,负责启动所有其他进程,它是所有进程的父进程,而init的父进程已经死亡,它负责在这些进程死亡时获取它们,由init管理的进程成为作业(jobs),由/etc/init目录中的文件定义

 

init的任务时在内核完全运行之后“让所有东西按照应有的方式运行”,本质上,它建立并操作整个用户空间,这包括检查和挂载文件系统,启动必要的用户服务,并最终在系统启动完成时切换到用户环境,它类似于Unix和BSD的init进程,但在某些情况下,它已经分化或定制了初始化进程。在一个标准的Linux系统中,init是用一个名为runlevel的参数执行的,该参数的值从0到6不等,该参数决定哪些子系统是可操作的,每个运行级别都有自己的脚本,这些脚本将设置或离开给定的运行级别时涉及的各种过程进行编码,引导过程中需要引用这些脚本,init脚本通常保存在名称为"/etc/rc..."的目录中,init的顶层配置文件位于/etc/inittab

 

在系统引导期间,它检查是否在/etc/inittab中指定了默认运行级别,如果没有,则请求运行级别通过系统控制台进入,然后,它继续为给定的运行级别运行所有相关的引导脚本,包括加载模块、检查根文件系统的完整性(根文件系统是只读挂载的)。然后重新挂载它以实现完全的读写访问,并设置网络。

 

在生成指定的所有进程之后,init进入休眠状态,并等待发生以下三种时间之一:开始结束或死亡的过程、电源故障信号或通过/sbin/telinit请求进一步更改运行级别。

 
 

6.2 Systemd

systemd的开发人员旨在替换从UNIX System V和Berkeley Software Distribution(BSD)操作系统继承而来的Linux init系统,与init一样,systemd也是一个守护进程,它管理其他守护进程,包括systemd,都是后台进程,Systemd是第一个启动的守护进程(在引导期间),也是最后一个终止的守护进程(在关闭期间)

 

最初开发systemd的软件工程师Lennart Poettering和Kay Sievers视图在几个方面超越init守护的效率,它们希望改进表示依赖关系的软件框架,允许在系统启动期间并行地进行更多处理,并减少shell的计算开销。

 

每个守护进程的Systemd初始化指令都记录在声明性配置文件中,而不是shell脚本中,对于进程间通信,systemd使Unix域套接字和D-Bus对正在运行的守护进程可用,Systemd还能够主动并行化。

 

以上资源摘自Wiki百科:https://en.wikipedia.org/wiki/Linux_startup_process

 
 


 
 

7. 详细的了解

要想通透的了解linux的启动过程,以下是必须了解的理论知识:

 
 

BIOS

(Basic Input/Output System)基本输入输出系统,也被称为System BIOS,ROM BIOS或PC BIOS,是非易失性的固件使用在开机过程中执行硬件的初始化(开机启动),并为操作系统和程序提供运行时服务。BIOS固件预安装在个人计算机的系统板上,是第一个打开电源时运行的软件。

大多数BIOS实现专门设计用于与特定计算机或主板模型一起使用,通过与构成互补系统芯片组的各种设备连接。最初,BIOS固件存储在PC主板上的ROM芯片中。在现代计算机系统中,BIOS内容存储在闪存中,因此可以在不从主板上移除芯片的情况下重写它。这允许对BIOS固件进行简单的最终用户更新,从而可以添加新功能或修复错误,但这也会使计算机感染BIOS rootkit。

 
 

FIRMWARE

固件,就是写入只读存储器中(ROM)的程序,例如计算机主板上的基本输入/输出系统BIOS,专业人士都叫他固件。由于早期固件芯片采用ROM设计,所以无法更改,随着技术的不断发展,可以使用EPROM(可擦写可编程只读存储器)或EEPROM(带电可擦可编程只读存储器)进行修改或升级。

 
 

POST

(Power-On Self-Test)加电自检是在计算机或其他数字电子设备开机后立即通过固件或软件程序执行的过程。POST的结果可以显示在作为设备一部分的面板上,输出到外部设备,或者存储以供将来通过诊断工具检索,例如自检可能检测到显示器不起作用,因此可以提供指示灯或扬声器以将错误代码显示为一系列闪烁、蜂鸣声或哔哔声...。在计算机的情况下,POST是设备的于启动序列的一部分,如果它们成功完成,则调用引导加载程序代码以加载操作系统。(POST是BIOS功能的一个主要部分)

 

Bootstrapping

(Booting)引导,是启动计算机的过程,特别是在启动其软件方面,该过程涉及一系列阶段,其中在每个阶段加载更小,更简单的程序,然后执行下一阶段更大、更复杂的程序,引导是一系列事件。例如,当计算机开机时,计算机首先执行一个存储在只读存储器(ROM)中相对小的程序,以及少量所需的数据,以访问RAM或磁盘,并将磁盘中的"操作系统"和"数据"加载到RAM中,以进行后续的操作。启动此序列的小程序被称为"引导加载程序"或"引导程序",这个小程序的唯一工作是加载其他数据和程序,然后从RAM中执行。

 
 

ROM

(Read-Only Memory)只读存储器,是计算机和其他电子设备中使用的一种非易失性存储器,存储在ROM中的数据只能慢慢修改,比较困难,或者根本不可能更改,因此它主要用来存储固件(不会经常更新的软件)。严格来说,只读存储器是指硬连接的存储器,制造后不能改变,在许多应用程序中,这样的内存永远无法更改是一个缺点,因为错误和安全的问题无法修复,并不能添加新特性。每个存储程序计算机可以使用一种非易失性存储的形式(即,在移除电源时保留其数据的存储器)来存储在通电时运行的初始程序(成为引导Bootstrapping)

 
 

RAM

(Random-access memory)随机存取存储内存,易失性存储器:当计算机关闭时,RAM磁盘会丢失存储的数据,除非将内存安排为备用电池电源。所谓随机存取,旨的是存储器中的数据被读取或写入时,所需要的时间与这段信息所在的位置或所写入的位置无关,相对的,读取或写入顺序访问(Sequential Access)存储设备中的信息时,其所需要的时间与位置就会有关系。它主要用来存放操作系统、各种应用程序、数据等。

根据存储单元的工作原理不同,RAM分为静态RAM和动态RAM。

 

静态随机存储器(SRAM)

特点是工作速度快,只要电源不撤除,写入SRAM的信息就不会消失,不需要刷新电路,同时在读出时不破坏原来存放的信息,一经写入可多次读出,但集成度较低,功耗较大。SRAM一般用来作为计算机中的高速缓冲存储器(Cache)

 

动态随机存储器(DRAM)

它将每一位数据存储在集成电路内的单独的微小电容器中。电容器可以充电或放电; 取这两种状态来表示的比特的两个值,通常称为0和1的电荷在电容器慢慢泄漏掉,所以无需干预,芯片上的数据会很快丢失,为防止这种情况,DRAM需要外部存储器刷新电路周期性地重写电容器中的数据,将它们恢复到原来的电荷。与不需要刷新数据的静态随机存取存储器(SRAM)相比,该刷新过程是动态随机存取存储器的定义特征。

 
 

MBR

(Master Boot Record)主引导记录,是一种特殊类型的引导扇区,在一开始就被划分出来,在512字节的主引导扇区中,MBR只占用了其中的446个字节,另外的64个字节交给了 DPT(Disk Partition Table硬盘分区表),最后两个字节“55,AA”是分区的结束标志。MBR扇区可能包含用于定位活动分区并调用其卷引导记录的代码。MBR保存有关如何在该介质上组织包含文件系统的逻辑分区的信息,MBR还包含可执行代码用作已安装操作系统的加载程序。通常是将控制权交给GRUB等其他引导加载程序,或者与每个分区的卷引导记录(VBR)一起使用。此MBR通常成为引导加载程序。MBR中分区表的组织将磁盘的最大可寻址存储空间限制为2TiB(2^32^x512字节),由于这种限制,基于MBR分区方案正在被新计算机中的GUID分区表(GPT)方案取代,GPT可以与MBR共存,以便为旧系统提供某种有限形式的向后兼容性。MBR不存在于非分区媒体上,例如,软盘或闪存之类的其他存储设备,因为这样的媒体被视为单个分区。

 
 

GTP

(GUID Partition Table)GTPS是用于布局的标准分区表的物理计算机存储设备,诸如硬盘驱动器或固态驱动器,使用全球唯一标识符(GUID),由于主引导记录(MBR)分区表的限制性,它构成了同意扩展固件接口(UEFI)标准的一部分。但它也用于某些BIOS系统,它使用32位进行逻辑块寻址(LBA)传统的512字节磁盘扇区。

所有现代个人计算机操作系统都支持GPT。一些(包括x86架构上的macOS和Microsoft Windows)仅支持在具有EFI固件的系统上从GPT分区启动,但FreeBSD和大多数Linux发行版可以从具有旧版BIOS固件接口和EFI的系统上的GPT分区启动。

 
 

VBR

(Volume Boot Record)卷引导记录,(也称为卷引导扇区,分区引导记录或分区引导扇区),它可以在分区数据存储设备(如硬盘)或为分区设备(如软盘)上找到,并包含存储在设备其他部分的引导程序(通常,但不一定是操作系统)的机器码。是尚未分区的数据存储设备的第一个扇区。或在已分区设备上,它是设备上单个分区的第一个扇区,整个设备的第一个扇区是包含分区表的主引导记录(MBR)。卷引导记录中的代码可以由机器的固件直接调用,也可以通过主引导记录(MBR)或引导管理器(GRUB)中的代码间接调用,MBR和VBR中的代码本质上以相同的方式加载。

通过引导管理器调用VBR称为链加载,将各个操作系统安装的引导代码的副本从VBR中复制,并存储在硬盘文件中,在引导加载程序询问用户引导哪个操作系统后,从文件加载相关的VBR内容。

 

扩展:Windows与Linux

例如一些双启动系统,流行的Linux和Windows操作系统,每个都包含在自己的分区中,Windows不支持多引导系统。但是大多数的Linux安装程序都适用于双启动(尽管需要一些分区知识)。但是在重新启动时,引导加载程序将仅识别两个操作系统中的一个,

安装Linux引导管理器/加载程序(通常是GRUB)作为主引导记录指向的主引导加载程序有一些优点,正确安装Linux引导加载程序可以找到Windows操作系统,但是Windows引导管理器无法识别Linux安装(Windows也不会与Linux文件系统交互)。

所以,通常建议将Windows安装到第一个主分区,Windows和Linux的引导加载程序通过计算分区来识别带有数字的分区,(注意,Windows和Linux都根据分区表中分区的顺序来计算分区,这可能与磁盘上分区的顺序不同)在硬盘末端添加或删除分区将对它之前的任何分区都没有影响,但是如果在硬盘驱动器的开头或中间添加或和删除分区,则后续分区的编号可能会更改,如果系统分区的编号发生更改,则需要重新配置引导加载程序,以便操作系统引导并正常进行。

必须将Windows安装到主分区(必须是第一个分区),Linux可以安装在硬盘驱动器上任何位置的分区中,也可以安装到逻辑分区(扩展分区内),如果Linux安装在扩展分区内的逻辑分区中,则它不受主分区中的更改影响。



 

GRUB2

GNU GRUB (GNU GRand Unified Bootloader, 通常称为GRUB)是GNU Project的一个引导加载程序包。GRUB是参考实现了的自由软件基金会的多引导规范,它提供了用户的选择来引导多个操作系统安装在计算机上,或者选择一个特定的内核在一个特定的操作系统的分区可用的配置。打开计算机是,BIOS会找到已配置的主要可引导设备,并从主引导记录(MBR)加载并初始引导程序(引导加载器,即GRUB)。

GRUB的两个主要版本是常用的:

  • GRUB版本1,称为GRUB,只在Linux发行版,其中一些仍然在使用,并支持老版本的流行,例如CentOS的 5 。
  • GRUB 2是从头开始编写和旨在取代其前身,现在被大多数Linux发行版使用。







 

拿CentOS7举例,这是我个人理解的启动过程:

 

(1)引导阶段

第一步:打开电源后(开机),计算机相对较笨,只能读取部分存储空间(ROM),由于ROM的特性,这时CPU处于只读模式。在ROM中,存储了一个称为固件的小程序(BIOS),它进行加电自检,检测硬件等(POST),最主要的是,允许访问其他类型的内存(硬盘或RAM)。BIOS存储了磁盘的启动顺序,BIOS按照顺序去找MBR。找到后会将MBR中的引导代码复制到RAM中(是一个446字节的boot.img镜像)。并转移控制权(CPU)。MBR本身还包含一个64字节的分区表,描述了分区的大小和其他属性。剩余的2字节用于磁盘签名。
(此步骤称为阶段1)

第二步:由于MBR引导程序不能理解文件系统的结构,因此它必须定位core.img然后加载到RAM中,并转移控制权。core.img代码必须位于MBR和第一个分区之间的位置,由于历史技术原因,第一个分区的扇区开始位置是63,可以计算(一个扇区为512bytes),62*512=31744,然后减去MBR占用的一个扇区31744-512=31232,而一个core.img的大小也就26676左右。在此注意,还有一个diskboot.img,它是core.img的第一个扇区(即整个磁盘的第二个扇区),其唯一目的是加载core.img中通用的文件系统的驱动,例如FAT,NTFS,EXT等。,这时就可以直接访问文件系统了(/boot文件)。(此步骤为阶段1.5)

第三步:core.img进入32位保护模式,然后加载/boot/grub2/i386-pc/normal.mod,normal.mod用于解析/boot/grub2/grub.cfg文件,可选择加载模块(例如,用于图形UI)并显示菜单。然后通过用户的选择(或者默认)将指定的内核加载到RAM中。并将控制权交给内核(此步骤为阶段2)



 

(2)内核阶段

 

加载阶段:内核同通常以镜像文件的形式加载,用zlib压缩成zImage或bzImage格式,内核作为压缩的镜像文件,将解压缩自身。

启动阶段:内核会立即初始化和配置计算机内存,并配置附加到系统上的各种硬件,包括所有处理器,I/O子系统和存储设备。然后它在内存中预定的位置查找压缩后的initrd(临时根文件系统),对其进行解压,然后内核启动虚拟内存交换器(它是一个内核进程)并创建一个根分区,以只读方式挂载,该initrd中包含各种可执行程序和驱动程序。然后内核创建初始用户空间进程执行/sbin/init,这里的init其实就是/usr/lib/systemd的链接文件(即调用systemd,其PID为1)。等待systemd将实际的根文件系统挂载后,再将initrd这个临时的根文件系统卸载。

在Centos7的/boot文件中有一个initrd-plymouth.img镜像文件,你可以解压看看:

[root@www ~]# cp /boot/initrd-plymouth.img ./initrd.img.gz
[root@www ~]# gunzip initrd.img.gz
[root@www ~]# cpio -i -d < initrd.img
2663 blocks
[root@www ~]# ls
bin  etc  initrd.img  lib64  sbin  usr



 

(3)初始化阶段

systemd是所有进程的父进程。也是一个守护进程,它管理其他守护进程。包括systemd,都是后台进程,systemd是第一个启动的守护进程(在引导期间),也是最后一个终止的守护进程(在关闭期间)。
首先systemd按照/etc/fstab文件中的配置进行挂载。再根据运行级别(通过/etc/systemd/system/default.target链接文件得知运行级别)然后启动该运行级别的一系列的依赖(详细的启动顺序可使用命令systemd-analyze plot > boot.html然后用浏览器查看)。最后执行getty.target启动终端和登陆程序。至此,整个过程结束。

 

以上是我个人理解,但还是有很多问题,例如最后,getty.target开启了终端,那么它是调用/bin/login还是getty.target本身就和/bin/login一样,这里还是很迷。

 

https://www.cnblogs.com/liuhedong/p/10661608.html

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值