系统通电,CPU首先执行固化在ROM中的BIOS(Basic Input Output System)。
BIOS最主要的一件事是硬件自检POST,并在启动盘(Windows一般是C盘系统盘)的第一个扇区(MBR)加载执行BootLoader。
BIOS工作在CPU和IO设备之间,因此他总是能知道计算机的所有硬件信息。如果任何的硬盘或IO设备发生变化,只需更新BIOS即可。BIOS被存储在RRPROM/FLASH内存中,BIOS不能存储在硬盘或者其他设备中,因为BIOS是管理这些设备的。BIOS使用汇编语言编写。
初始化硬件设备,检查系统外围主要设备(CPU,内存,硬盘,显卡,I/O设备,键盘鼠标)是否存在故障影响正常开机。
下一步,根据BIOS设置的启动顺序,检测驱动器(硬盘,光盘,U盘,网络),如果硬盘是启动项,读取硬盘第一个扇区(MBR,512字节)到内存,控制区转给MBR中的BootLoader。
因为我们在给磁盘分区的时候,第一个扇区一般会保留一些初始化启动代码,这里的MBR就是磁盘分区的第一个扇区,大小512Bytes。
MBR由主引导程序、硬盘分区表DPT和有效硬盘标识组成。
MBR的BootLoader中安装有GRUB程序的一部分,因为BootLoader只有446Bytes,容量太小,所以只安装了GRUB中一个小的程序在里面,用于加载剩余的GRUB程序。
BIOS确认硬件没有问题之后,就要加载执行BootLoader了,BootLoader一般放在外部的存储介质中比如磁盘,也就是我们俗称的启动盘(OS也装在其中),BootLoader并不是一次就可以全部加载的,首先会去寻找加载MBR中的代码,找到GRUB的最小部分,再分阶段进行加载。
GRUB程序的作用是,可以在系统中选择性地引导不同的OS,实际上就是加载引导不同的内核镜像,当内核挂载成功之后就将控制权交给内核程序。
Stage1可以理解为已写入MBR的BootLoader中的小程序部分。因为MBR空间有限,所以MBR当中安装最小程序。其主要作用是装载Stage2,即加载剩余的GRUB程序。
Stage1.5是MBR后面的分区,并不处在MBR中。它是Stage1和Stage2的桥梁,能够识别启动分区文件系统,GRUB访问/boot分区grub目录下的Stage2文件,将Stage2载入内存并执行。
Stage2运行后,开始解析GRUB的配置文件/boot分区下/grub/grub.conf。然后显示操作系统启动菜单,加载内核镜像到内存,通过/boot/initrd开头文件建立虚拟RAM DISK虚拟内存文件系统,最后将控制权转交给内核程序。
依靠Stage2阶段在内存中创建的虚拟文件系统,从中调用虚拟根文件系统中的init程序,进而加载驱动模块来初始化系统中的各设备,并做相关配置,其中包括CPU、I/O、存储设备等。
当所需的驱动程序加载完后,会根据grub.conf配置文件中“root=XXX”部分所指定的内容创建一个根设备,然后将根文件系统以只读的方式挂载,并切换到真正的根文件系统上,同时调用系统进程的/sbin/init程序,进入系统初始化阶段。
这一步是通过/sbin/init,init程序准备软件运行环境,启动系统服务。
init 进程是系统所有进程的起点,你可以把它比拟成系统所有进程的老祖宗,没有这个进程,系统中任何进程都不会启动。
Linux系统有7个运行级别(runlevel):
默认级别:3,5
切换级别:init #
查看级别:runlevel ; who -r
init 程序首先是需要读取配置文件 /etc/inittab。通过/etc/inittab文件确定运行级别,然后去执行系统初始化脚本/etc/rc.sysinit,为用户初始化用户空间环境,在完成初始化后,根据运行级别,系统开始对应级别的目录启动服务,关闭那些不要的服务。
好像Ubuntu没有inittab文件。有了解的朋友评论区给个答案。
[root@centos6 ~]#vim /etc/inittab
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:5:initdefault:
init确定了运行级别后,还调用执行了/etc/rc.d/rc.sysinit或/etc/rc.sysinit,而rc.sysinit是一个bash shell的脚本,它主要是完成一些系统初始化的工作,rc.sysinit是每一个运行级别都要首先运行的重要脚本。
它主要完成的工作有:激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务。
/etc/rc.d/rc是一个Shell脚本,作用是当运行级别切换时用于启动或停止服务。它接受0~6作为参数,去执行/etc/rc.d/rc#.d/目录下的所有的rc启动脚本(#表示0-6任一数字),/etc/rc.d/rc#.d/目录中的这些启动脚本实际上都是一些连接文件,而不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。
而这些rc启动脚本有着类似的用法,它们一般能接受start、stop、restart、status等参数。
/etc/rc.d/rc#.d/中的rc启动脚本通常是K或S开头的连接文件。对于以 S 开头的启动脚本(例S##*),将以start参数来运行。而如果发现存在相应的脚本也存在K打头的连接(例K##*),而且已经处于运行态了,则将首先以stop为参数停止这些已经启动了的守护进程,然后再重新运行。其中## 是数字,表示优先级,数字越小,越优先启动/关闭。
这样做是为了保证是当init改变运行级别时,所有相关的守护进程都将重启。
至于在每个运行级中将运行哪些守护进程,用户可以通过chkconfig或setup中的"System Services"来自行设定。
[root@centos6 ~]#ls /etc/rc.d/rc5.d/
K01smartd K75quota_nld S10network S26acpid
K02oddjobd K76ypbind S11auditd S26haldaemon
K05wdaemon K84wpa_supplicant S11portreserve S26udev-post
K10psacct K87restorecond S12rsyslog S28autofs
K10saslauthd K88sssd S13cpuspeed S50bluetooth
K15htcacheclean K89netconsole S13irqbalance S55sshd
K15httpd K89rdisc S13rpcbind S56xinetd
K50dnsmasq K92iptables S15mdmonitor S70spice-vdagentd
K50kdump K92pppoe-server S22messagebus S80postfix
K60nfs K95firstboot S23NetworkManager S82abrtd
K61nfs-rdma K99rngd S24nfslock S83abrt-ccpp
K69rpcsvcgssd S01sysstat S24rpcgssd S90crond
K73winbind S02lvm2-monitor S25blk-availability S95atd
K74ntpd S05rdma S25cups S99certmonger
K75ntpdate S08ip6tables S25netfs S99local
用于加载用户自定义的服务。
rc执行完毕后,返回init。这时基本系统环境已经设置好了,各种守护进程也已经启动了。
init接下来会打开6个终端,以便用户登录系统。在inittab中的以下6行就是定义了6个终端:
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
从上面可以看出在2、3、4、5的运行级别中都将以respawn方式运行mingetty程序,mingetty程序能打开终端、设置模式。
同时它会显示一个文本登录界面,这个界面就是我们经常看到的登录界面,在这个登录界面中会提示用户输入用户名,而用户输入的用户将作为参数传给login程序来验证用户的身份。
一般来说,用户的登录方式有三种:
Linux 的账号验证程序是 login,login 会接收 mingetty 传来的用户名作为用户名参数。
/etc/nologin文件:如果用户在该文件中,则不许登录。
/etc/usertty文件:用于对用户作出附加访问限制,如果不存在这个文件,则没有限制。
/etc/securetty文件:登记在其中的终端才允许用户登录,如果不存在该文件,则任何终端上都可以登录。
/etc/passwd & /etc/shadow文件:用来验证密码以及设置账户的主目录是什么、使用何种shell。
命令行终端屏幕根据/var/log/lastlog输出最近一次登录的信息,以及根据/var/spool/mail/USERNAME输出用户是否有新邮件。
同时根据文件/etc/profile、.bash_profile、.bash_login、.profile
文件加载环境变量。
参考文章
http://www.yunweipai.com/33942.html
https://www.runoob.com/linux/linux-system-boot.html
https://www.jb51.net/article/145422.htm
https://blog.csdn.net/weixin_42255666/article/details/82501831
https://www.cnblogs.com/quan0311/p/15292110.html#12-post