linux开机逻辑

linux开机逻辑

理解开机原理是理解linux系统的很重要的一个环节。在开发中也常常会遇到需要把一些服务加入开机启动等问题。有的时候查了资料加成功了,也往往是知其然不知其所以然。这篇文章我结合网上的资料总结下linux的开机逻辑。一起加深对linux的理解。


启动流程图

image

启动详细过程

BIOS

加载BIOS的硬件信息并进行自我测试 当打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PnP特性等等。在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了。

MBR

硬盘上第0磁道第一个扇区被称为MBR,也就是Master Boot Record,即主引导记录,它的大小是512字节,别看地方不大,可里面却存放了预启动信息、分区表信息。系统找到BIOS所指定的硬盘的MBR后,就会将其复制到0x7c00地址所在的物理内存中。其实被复制到物理内存的内容就是Boot Loader,而具体到你的电脑,那就是lilo或者grub了。

Boot Loader

Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核做好一切准备。通常,BootL oade:是严重地依赖于硬件而实现的,不同体系结构的系统存在着不同的Boot Loader。

Linux的引导扇区内容是采用汇编语言编写的程序,其源代码在arch/i386/boot中(不同体系的CPU有其各自的boot目录),有4个程序文件:

  • ootsect.S,引导扇区的主程序,汇编后的代码不超过512字节,即一个扇区的 大小
  • etup.S, 引导辅助程序
  • dd.S,辅助程序的一部分,用于支持BIOS增强磁盘设备服务
  • ideo.S,辅助程序的另一部分,用于引导时的屏幕显示   

Boot Loader有若干种,其中Grub、Lilo和spfdisk是常见的Loader,这里以Grub为例来讲解。

GRUB2

GRUB2 全称是 GRand Unified BootLoader,Version 2(第二版大一统引导装载程序)。它是目前流行的大部分 Linux 发行版本的主要引导加载程序。GRUB2 是一个用于计算机寻找操作系统内核并加载其到内存的智能程序

GRUB 被设计为兼容操作系统多重引导规范,它能够用来引导不同版本的 Linux 和其他的开源操作系统;它还能链式加载专有操作系统的引导记录。

GRUB 允许用户从任何给定的 Linux 发行版本的几个不同内核中选择一个进行引导。这个特性使得操作系统,在因为关键软件不兼容或其它某些原因升级失败时,具备引导到先前版本的内核的能力。 GRUB1 能够通过文件 /boot/grub/grub.conf 进行配置。

GRUB1 现在已经逐步被弃用,在大多数现代发行版上它已经被 GRUB2 所替换,GRUB2 是在 GRUB1 的基础上重写完成。基于 Red Hat 的发行版大约是在 Fedora 15 和 CentOS/RHEL 7 时升级到 GRUB2 的。GRUB2 提供了与 GRUB1 同样的引导功能,但是 GRUB2 也是一个类似主框架(mainframe)系统上的基于命令行的前置操作系统(Pre-OS)环境,使得在预引导阶段配置更为方便和易操作。GRUB2 通过 /boot/grub2/grub.cfg 进行配置。

两个 GRUB 的最主要作用都是将内核加载到内存并运行

Load Kernel

内核文件都是以一种自解压的压缩格式存储以节省空间,它与一个初始化的内存映像和存储设备映射表都存储于 /boot 目录之下。

在选定的内核加载到内存中并开始执行后,在其进行任何工作之前,内核文件首先必须从压缩格式解压自身。一旦内核自解压完成,则加载 systemd 进程(其是老式 System V 系统的 init 程序的替代品),并转移控制权到 systemd。

这就是引导过程的结束。此刻,Linux 内核和 systemd 处于运行状态,但是由于没有其他任何程序在执行,故其不能执行任何有关用户的功能性任务。

根据grub设定的内核映像所在路径,系统读取内存映像,并进行解压缩操作。此时,屏幕一般会输出“Uncompressing Linux”的提示。当解压缩内核完成后,屏幕输出“OK, booting the kernel”。 系统将解压后的内核放置在内存之中,并调用start_kernel()函数来启动一系列的初始化函数并初始化各种设备,完成Linux核心环境的建立。至此,Linux内核已经建立起来了,基于Linux的程序应该可以正常运行了。

Init

在硬件驱动成功后,Kernel会调用init进程,init是Linux系统操作中不可缺少的程序之一。

所谓的init进程,它是一个由内核启动的用户级进程。 内核自行启动(已经被载入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以,init始终是第一个进程(其进程编号始终为1)。 内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init。如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。

Set Run-level

内核被加载后,第一个运行的程序便是/sbin/init,该文件会读取/etc/inittab文件,并依据此文件来进行初始化工作。 其实/etc/inittab文件最主要的作用就是设定Linux的运行等级,其设定形式是“:id:5:initdefault:”,这就表明Linux需要运行在等级5上。Linux的运行等级设定如下:

  • 0:关机
  • 1:单用户模式
  • 2:无网络支持的多用户模式
  • 3:有网络支持的多用户模式
  • 4:保留,未使用
  • 5:有网络支持有X-Window支持的多用户模式
  • 6:重新引导系统,即重启

rc.sysinit

系统知道自己的启动等级后,接下来,不是去启动服务,而是,先设置好主机运行环境。读取的文件是/etc/rc.d/rc.sysinit文件。那究竟要设置哪些环境呢?

  • 获取网络环境与主机类型。首先会读取网络环境设置文件”/etc/sysconfig/network”,获取主机名称与默认网关等网络环境。
  • 测试与载入内存设备/proc及usb设备/sys。除了/proc外,系统会主动检测是否有usb设备,并主动加载usb驱动,尝试载入usb文件系统。
  • 决定是否启动SELinux。
  • 接口设备的检测与即插即用(pnp)参数的测试。
  • 用户自定义模块的加载。用户可以再”/etc/sysconfig/modules/*.modules”加入自定义的模块,此时会加载到系统中。
  • 加载核心的相关设置。按”/etc/sysctl.conf”这个文件的设置值配置功能。
  • 设置系统时间(clock)。
  • 设置终端的控制台的字形。
  • 设置raid及LVM等硬盘功能。
  • 以方式查看检验磁盘文件系统。
  • 进行磁盘配额quota的转换。
  • 重新以读取模式载入系统磁盘。
  • 启动quota功能。
  • 启动系统随机数设备(产生随机数功能)。
  • 清楚启动过程中的临时文件。
  • 将启动信息记录到”/var/log/dmesg”文件中。

rcx.d(x:0~6)

接下来,就是启动系统服务了,不同的run-level会有不同的服务启动。到/etc目录中,不同的level会有不同的目录。如启动 3模式,会有个rc3.d目录,里面就保存着服务。其中,S(start)开头的表明开机启动,K(kill)开头的表明开机不启动。数字表示启动顺序。数字越小,启动越早。

lrwxrwxrwx.  1 root root   15 Sep  7 15:36 S64mysql -> ../init.d/mysql
lrwxrwxrwx.  1 root root   17 Mar  8  2017 S75haveged -> ../init.d/haveged
lrwxrwxrwx.  1 root root   18 Sep  7 15:07 S80sendmail -> ../init.d/sendmail
lrwxrwxrwx.  1 root root   15 Sep  7 15:07 S90crond -> ../init.d/crond
lrwxrwxrwx.  1 root root   20 Sep 10 01:16 S90finalspeed -> ../init.d/finalspeed
lrwxrwxrwx.  1 root root   18 Sep  9 16:08 S90tcpspeed -> ../init.d/tcpspeed
lrwxrwxrwx.  1 root root   11 Sep  9 16:06 S99local -> ../rc.local

注意,他们都是连接到etc/rc.d/init.d/目录中的相关文件。所以,想手工启动某一服务,可以用”/etc/rc.d/init. d/某个服务 start”启动。相反,我们也可以把某个服务ln(链接命令)到不同run-level的目录中。记得打上S或者K+数字。

在rcx.d目录的最后一行执行了rc.local

S99local -> ../rc.local

rc.local

你如果打开了此文件,里面有一句话,读过之后,你就会对此命令的作用一目了然:

# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don’t
# want to do the full Sys V style init stuff.

rc.local就是在一切初始化工作后,Linux留给用户进行个性化的地方。你可以把你想设置和启动的东西放到这里。 例如:

/usr/bin/ssserver -s ::0 -p `cat /root/.kiwivm-shadowsocks-port` -k `cat /root/.kiwivm-shadowsocks-password` -m `cat /root/.kiwivm-shadowsocks-encryption` --user nobody --workers 2 -d start

/etc/init.d/finalspeed start

mingetty(login)

init执行终端机模拟程序mingetty来启动login进程,最后就等待用户登录。

补充知识点

补充1:chkconfig命令

chkconfig命令检查、设置系统的各种服务。这是Red Hat公司遵循GPL规则所开发的程序,它可查询操作系统在每一个执行等级中会执行哪些系统服务,其中包括各类常驻服务。谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接。 具体使用方法介绍参见chkconfig命令

补充2:添加开机启动服务

在linux下安装了apache 服务(通过下载二进制文件经济编译安装、而非rpm包)、apache 服务启动命令:/server/apache/bin/apachectl start。让apache服务运行在运行级别3下面。 命令如下:

touch /etc/rc.d/init.d/apache
vi /etc/rc.d/init.d/apache
chown -R root /etc/rc.d/init.d/apache
chmod 700 /etc/rc.d/init.d/apache
ln -s /etc/rc.d/init.d/apache /etc/rc.d/rc3.d/S60apache

S是start的简写、代表启动、K是kill的简写、代表关闭。60数字 代表启动的顺序。

apache的内容:

#!/bin/bash
#Start httpd service
/server/apache/bin/apachectl start

至此 apache服务就可以在运行级别3下 随机自动启动了。(可以结合chkconfig 对启动服务进行相应的调整)。

发表评论

电子邮件地址不会被公开。 必填项已用*标注