Linux系统启动流程、grub修复、模块管理及内核参数设定
runlevel, who -r , chkconfig ,grub ,grub-install , mkinitrd , dracut ,sysctl ,lsmod ,modinfo , modprobe , depmod , insmod ,rmmod
Linux系统的组成部分


kernel

/boot/vmlinuz-VERSION-RELEASE


initrd

Centos 5 : /boot/initrd-VERSION-RELEASE.img
Centos 6/7 : /boot/initramfs-VERSION-RELEASE.img


filesystem


模块文件

一般存放于/lib/modules/$(uname -r)/目录下


内核的设计流派

单内核设计
把所有功能集成于同一个程序中,其中linux就是以单内核设计


微内核设计
每个功能使用一个单独的子系统实现,每个子系统通信需有特殊的机制来实现,其中winodows、solaris的内核设计方式就为微内核。


Linux内核的特点

单内核设计
支持模块化(.ko的文件,[]kernel object])
支持模块运行时动态装载或卸载
内核可以将驱动模块或者功能模块编译进内核,由内核初始化直接加载完成

linux启动流程示意(内核空间---用户空间)


内核空间

POST—>BootSequence(BIOS)—>bootloader(MBR)—>kernel(ramdisk) —>rootfs(只读方式挂载)—> /sbin/init


用户空间:

/sbin/init(/etc/inittab) --> { id:#:initdefault: --> si::sysinit:/etc/rc.d/rc.sysinit --> l#:#:wait:/etc/rc.d/rc # --> /etc/rc.d/rc#.d/[1、开始S开头的服务;2、结束K开头的服务]}-->/etc/rc.d/rc.local
注意:以上{}中,表示在/etc/inittab文件中完成的步骤。



内核空间启动步骤
1、POST加电自检

当按主机电源键,计算机主板通电,并完成已下操作:
加载Bios中的ROM中的程序,来检测各种硬件设备Bios : Baisc input and output system



2、BootSequence

按bootsequence的启动列表,查找MBR或UEFI的活动设备。

3、Bootloader

找到MBR后查找引导加载器(bootloader程序),读取mbr中的bootloader,加载boootloader中的grub程序

Grub的工作原理

stage1: 加载mbr中的所有分区信息
stage1.5: mbr之后的扇区,让stage1中的bootloader能识别stage2所在的文件分区上的文件系统
stage2: 磁盘分区之上(/boot/grub/)

注意:MBR能识别基本的硬盘设备,但不能识别高级的文件系统,如lvm , raid等
Bootloader的类型及使用场景

ntloader
windows


LILO(linux loader)
早期的Linux系统
安卓手机设备


grub(Grand Uniform bootloader)
Centos 5/6 (grub 0.X)
Centos 7 (grub 1.X)


4、加载虚根文件系统(ramfs)

完成虚根ramfs的初始化,以此来识别硬盘上的文件系统。

5、挂载rootfs

以只读方式挂载根文件系统

6、初始化init进程

运行进程ID为1的Init进程,利用init启动流程完成用户空间的启动步骤

用户空间启动步骤
SysVinit进程的初始化


读取/etc/inittab,需完成如下加载步骤:

系统运行级别加载:id:#initdefault:
si::sysinit:/etc/rc.d/rc.sysinit : 加载运行/etc/rc.d/rc.sysinit文件,完成如下动作:
激动Udev和selinux
根据/etc/sysctl.conf文件,来设置内核参数
设定系统时钟
装载键映射
启用交换分区
设置主机名
要文件系统检测,并以读写方式重新挂载
激活raid和lvm设备
启用磁盘配额
根据/etc/fstab检测并挂载所有文件系统
清理过期的锁和PID文件


l0:0:wait:/etc/rc.d/rc 0 ---> /etc/rc.d/rcX.d/* 对应系统运行级别,开启或关闭系统各服务,如下:
停止K*的服务
启动S*开头的服务
以上服务都由chkconfig命令管理,并由service命令调用执行停止或关闭操作。



tty6:2345:respawn:/usr/sbin/mingetty tty6,启动登录窗口,并打印欢迎界面
其是mingetty调用login程序,完成密码验证过程


加载/etc/rc.d/rc.local文件
此文件是系统最后启动的一个文件,可以将不需要写在服务维护脚本的命令放置在这里,它将会随系统一起启动完成。



注意:

Centos7的init程序为systemd,其配置文件存放于:/usr/lib/systemd/system/ ; /etc/systemd/system/

Centos6的init为upstart,但为了兼容SysV风格,名称也为Init,其配置文件放置于/etc/init/*.conf

upstart的初始化流程
/etc/inittab(定义了默认的运行级别)-->/etc/init/rc.conf(其中定义了相应的运行级别所要执行对应级别下的服务/etc/rc.d/rcX.d/ ,根据命令exec /etc/rc.d/rc $RUNLEVEL 来调用`/etc/rc.d/rcX.d/`)-->/etc/rc.d/rc.local
================
/etc/inittab文件格式说明

id:runlevel:action:process
id: 一个任务的标识
runlevel: 在哪些级别下启动此任务,可以为空,即表示所有级别
action:在什么条件下启动此任务
wait : 等待切换至此任务所在的级别时执行一次
respawn : 设定默认运行给别,此时process省略
sysinit: 设定系统初始化方式,此处一般为指定/etc/rc.d/rc.sysinit脚本


process:任务


示例
    0:0:wait:/etc/rc.d/rc 0 : 意味着去启动或者关闭/etc/rc.d/rc3.d/目录下的服务脚本所控制的服务,所有K开头的要停止的服务,所有S开头的启动。 其中表示优先级,K中数值越小,表示越先关闭,S中数据越小表示越先开启。一般依赖的服务先关闭,然后再关闭被依赖的。或者一般被依赖的服务先启动,依赖的服务后启动
============
运行级别:

0:关机,shutdown
1: 单用户模式,(single user) root用户,无须认证登陆
2:多用户模式(multi user),会启动网络功能,但不会启动NFS;维护模式
3:多用户模式(multi user),完全功能模式,文本界面
4:预留级别:目前无特别使用目的。但习惯与同3级别功能使用
5: 多用户模式:(multi user),完全功能模式,图形界面。
6: 重启,reboot

查看系统运行级别

runlevel
who -r
systemctl get-default(Centos 7)

=========
系统服务类脚本的添加和管理
添加一个脚本格式
    #!/bin/bash
    #
    #chkconfig: 2345 50 60 #表示2345开启,其他关闭
    #description XXXXX
    下面是脚本正文,需要接受至少如下四个参数:
    {start|stop|restart|status}
使用chkconfig命令添加服务及管理

首先需要将脚本复制至/etc/init.d/中。
再使用chkocnfig --add 脚本名称(服务名称)
再使用service 脚本服务 start

=============
chkconfig命令

chkconfig --add service_name
添加一个服务脚本


chkconfig --del service_name
删除一个服务脚本


chkconfig --list
查看所有服务的启动状态


chkconfig 2345 service_name on
在2345运行级别启用此服务


chkconfig 2345 service_name off
在2345运行级别下关闭此服务


grub如何识别设备

1、Boot需单独分区
grub的位置应该为/grub/vmlinz


2、识别磁盘都为hd
(hd#,#) : 第一个表示磁盘分区,第二个#表示分区,都用数字表示,从零开始编号


grub的命令行接口

help:获取帮助列表
help KEYWORD : 详细帮助信息
find (hd#,#)/PATH/TOSOMFILE
find (hd0,0)/vmlinuz-2.6.32
root(hd0,0)  :把那个设备设置为根设备

kernel /path/to/kernel_file: 设定本次启动时用到的内核文件,额外还可以添加许多内核使用的command参数
      例如:init=/path/to/init, selinux=0,quiet

initrd /path/to/initramfs_file | initrd_file : 设定为选定的内核提供额外文件的ramfs(必须与内核版本号完全匹配)
boot:引导启动选定的内核   

手动在grub命令行接口启动系统:
grub> root(hd0,0)
grub> kernel /vmlinuz-version-release ro root=/dev/DEVICE
grub> initrd /initramfs-version-release.img
grub> boot

注意:ro : 表示以只读方式挂载根文件系统
     root=/dev/DEVICE : 应该写根文件系统所在的磁盘分区
grub的文件的配置格式
/etc/grub/grub.conf
default=0  # 设置默认启动的tile,0表示第一个tile
timeout=5    # 在启动时选择tile时的超时时间
hiddenmenu #是否隐藏启动界面
password --md5 密码串(使用grub-md5-crypt工具加密的密码串)#如果加密,编辑grub时会要求输入密码
title (Centos 6.6)  #启动时的菜单名称
    root (hd0,0) # 表示kernel的存放位置,hd统一表示为所有硬盘,第一个0表示第一块硬盘,第二个0表示一个分区
    kernel /vmlinuz.VERSION.release #kerenl文件的存放路径
    initrd /initramfs.VERSION.release.img #initramfs的存放路径
    password --md5 密码串 #这个密码加密后,启动相应的内核时,会要求输入密码


    #注意:title中的每一行都必须要缩进一个空白字符,当grub损坏时,可以使用"find (h0,0)/"查找目录下的文件,使用TAB键补全,如果有就会列出所有的文件,如果没有,表示(hd0,0)指定有错误,需再查找其他的分区中是否有。
进入单用户模式:

1、编辑grub菜单(选定要编辑的title ,e命令)
2、在选定的kernel后附加1,S,s 或者single都可以
3、在kernel所在行,键入b命令       

手动安装grub的方法


1、grub-install --root-directory=/mnt /dev/sdb
  注意:--root-directory=/mnt : 这个位置必须指定为boot目录所在的父目录,grub会自行在父目录中找到boot目录,然后把grub程序安装到对应的目录中,一般情况在挂载新预备安装gurb的硬盘时,需要在文件系统上建立一个boot目录,再把对应的磁盘挂到boot目录中,这样grub才会找到boot目录,在下面建立所需的文件,如果挂载时不创建boot目录,那和以grub会在目录下创建boot目录,启动时需要将kernel和initrd的位置就应该为/boot/vmliunz格式


2、分步骤安装
  grub
  grub> root (hd0,0)
  grub> setup (h0,0)


手动修复grub引导程序
模拟损坏mbr

dd if=/dev/zero of=/dev/sda bs=200 count=1
需要先备份好mbr,使用dd if=/dev/sda of=/root/sda bs=512 count=1



修复过程

1、挂载安装光盘,执行linux rescue 进行急救模式
2、chroot /mnt/sysp_w_picpath
3、执行grub-install --root-directory=/ /dev/sda        /dev/sda : 这是对磁盘的mbr修复指定位置,必须是磁盘,不能是分区,就是mbr所存放的位置


新加硬盘,提供直接单独运行bash系统
####创建文件系统并挂载
mke2fs -t ext4 /dev/sdb1
mke2fs -t ext4 /dev/sdb2
mkdir /media/boot
mount /dev/sdb1  /media/boot/
grub-install --root-directory=/media /dev/sdb
cp /boot/vmlinuz-2.6.32-573.el6.x86_64 /media/boot/vmlinuz
cp /boot/initramfs-2.6.32-573.el6.x86_64.img /media/boot/initramfs.img
####grub配置文件信息
vim /media/boot/grub/grub.conf
    default=0
    timeout=5
    hiddenmenu
    title (Centos6.6)
        root (hd0,0)
        kernel /vmlinuz ro root=/dev/sda2 selinux=0 init=/bin/bash
        initrd /initramfs.img
####给根文件系统提供bash和相应的库文件
mount /dev/sdb2 /mnt/
cd /mnt/
mkdir $(ls /) -pv
cp /bin/bash /mnt/bin/bash
ldd /bin/bash
cp /lib64/libtinfo.so.5 /mnt/lib64/
cp /lib64/libdl.so.2 /mnt/lib64/
cp /lib64/libc.so.6 /mnt/lib64/
cp /lib64/ld-linux-x86-64.so.2 /mnt/lib64/
chroot /mnt/
ramfs文件的管理
1、mkinitfs 命令(Centos5)

synopsis: mkinitrd [OPTION...] []

示例:

mkinitrd /boot/initramfs-$(uname -r).img $(uname -r)

2、dracut 命令(Centos 6\7)
示例:

dracut /boot/initramfs-$(uname -r).img $(uname -r)

内核信息输出的伪文件系统:


1、/proc目录


内核状态及统计信息的输出接口,同时还提供了一个配置接口:/proc/sys,可以使用sysctl命令修改其内核参数,其此目录下的大部分文件都可接受用户指定的一个"新值",来实现对内核某功能或特性的配置


2、/sys目录

输出内核识别出的各种配置设备的相关信息,也有内核对硬件特性的可设置参数,可定制硬件的特性

udev功能


通过读取sys目录下的硬件设备信息,按需为各硬件设备创建设备文件。当系统初始化的过程中,会探测计算机各种硬件设备信息,此记录会保存至/sys目录下,当系统启动完成后,udev会按照/sys目录下的各设备文件,创建相应的硬件信息。udev为设备创建设备文件时,会读取其事先定义好的规则文件,一般在其工作目录下。


udev的工作目录

/etc/udev/rules.d  : 自定义的规则目录
/lib/udev/rules.d/ : 默认的规则目录
/dev/.udev/rules.d : 临时规则目录存放位置(Centos 7才有)


udev目录下的文件
  root@zhenping rules.d]# ls /lib/udev/rules.d/
  01-log-block.rules           60-persistent-storage-tape.rules  75-cd-aliases-generator.rules          81-kvm-rhel.rules
  10-console.rules             60-persistent-v4l.rules           75-net-description.rules               88-clock.rules
  10-dm.rules                  60-wacom.rules                    75-persistent-net-generator.rules      90-pulseaudio.rules
  11-dm-lvm.rules              61-mobile-action.rules            75-tty-description.rules               91-drm-modeset.rules
  13-dm-disk.rules             61-option-modem-modeswitch.rules  77-mm-ericsson-mbm.rules               95-devkit-power-battery-recall-dell.rules


内核参数调整方法
1、配置文件修改(永久有效,但需重新启动后)


修改/etc/sysctl.conf 或者/etc/sysctl.d/*.conf
  net.ipv4.ip_forward = 0


注意:如果需要修改后的参数立即有效,需使用sysctl -p 命令重读其配置信息加载到内核中。
2、使用命令进行修改(临时有效,下次重启后丢失)
sysctl命令
sysctl -sysctl - configure kernel parameters at runtime


synopsis :  sysctl [options] [variable[=value]] [...]


[options]


-a : 显示当前可配置的所有参数

-w VAR=VLUE : 更改参数值

-p : 从/etc/sysctl.conf文件中重新加载内核设定值


示例

sysctl net.ipv4.ip_forward : 查看其值
sysctl -w kernel.hostname=zhenping.mac : 设置其计算机名为zhenping.mac
sysctl -a : 查看所有可配置的内核参数

使用文件系统命令cat和echo设置和查看

cat /proc/sys/kernetl/hostname
echo "VALUE" > /proc/sys/kernel/hostname

常见内核参数

net.ipv4.ip_forward : 核心转发功能
vm.drop_caches : 释放buff/cache空间,值有0\1\2
kernel.hostname : 主机名
net.ipv4.icmp_echo_ignore_all : 忽略所有发往自己的ping操作

模块管理
lsmod命令

lsmod - 查看所有系统被装载的模块


lsmod 
显示系统被装载的所有模块


注意:其是提取/proc/modules文件信息
=========
modinfo命令

modinfo - Show information about a Linux Kernel module
其通过/lib/modules/[KERNEL-VERSION]/modules/下的所有文件进行分析并显示的,默认情况下在内核modules编译安装的时候,会在其目录下生成所有modules的依赖关系等,建立对应的索引信息


synopsis : modinfo [-0] [-F field] [-k kernel] [modulename|filename...]


[options]


-k MODULE : 查看指定的模块信息

-F FIELD : 只显示指定字段的信息

-n MODULE 显示指定模块的存放路径


=====
modprobe命令:

modprobe - Add and remove modules from the Linux Kernel

synopsis: modprobe [-r] module_name

示例:

modprobe MODULE : 装载指定的模块文件
modprobe -r MODULE : 卸载指定的模块文件

modprobe可以自行解决模块与模块的依赖关系,并将依赖的模块也一并启用
====
depmod命令
内核模块依赖关系文件的生成工具,系统模块的生成文件路径为:/lib/modules/KERNEL-VERSION/下
======
模块装载和卸载的另一组命令:
insmod命令

insmod /lib/modules/3.10.0-229.el7.x86_64/kernel/fs/btrfs/btrfs.ko (模块一定要为完整路径)

rmmod命令

rmmod MODULE : 卸载指定的模块