从上一篇介绍了系统启动流程可以得知,在BIOS读取相关信息之后,接下来就是去找第一个可以启动的设备当中的MBR中读取Boot Loader信息,Boot Loader提供具有惨淡功能,直接加载内核信息,以及相关的控制权转交功能。启动系统必须有Boot Loader,然后才能去加载内核,Boot Loader存储于MBR当中,MBR只有512字节,其中前446字节存储Boot Loader,区区只有446自己不可能容纳较多的功能,Linux将Boot Loader的程序运行与配置项加载分成三个阶段来运行
stage1:运行Boot Loader主程序,这个程序必须安装在启动分区中,即MBR,因为MBR的空间有限,因此在MBR当中进安装Boot Loader的最小主程序,没有安装Boot Loader相关的配置文件
stage1_5:在MBR随后的扇区存放的是文件系统所需要的驱动程序
stage2:通过Boot Loader加载所有配置文件及相关的环境参数信息,这些配置文件及相关的环境都存放在磁盘分区的/boot目录下
在此大家一起回忆下系统的启动流程
POST(加电自检)-->Boot Sequence(BIOS)Boot Loadter-->kernel(ramdisk)rootfs
-->switchroot/sbin/init-->(/etc/inittab,/etc/init/*.conf)设定默认运行级别系统初始化脚本rc.sysinità关闭或启动对应级别的服务启动终端
grub:Grand Unified Bootloader
grub 0.X(版本号) grub legacy(之前教老的系统用的事0.9的版本)
grub 1.x:grub2
grub legacy
stage1:mbr
stage1_5:mbr之后的扇区,让stage1中的boot loader能识别stage2所在分区上的文件系统
stage2:磁盘分区(/boot/grub/)
配置文件/etc/grub/grub.confà/etc/grub.conf 此文件是个链接文件,真正的文件指向/boot/grub/grub.conf
stage2及内核通常放在一个单独的磁盘分区
grub的功能
1、提供启动菜单、并提供交互接口
a:编辑内核参数
e:编辑模式,用于编辑菜单
c:命令模式,交互式接口
2、加载用户选择的内核或操作系统
允许传递参数给内核如max_loop=100,给系统100个loop设备
可隐藏启动菜单
3、为菜单提供了保护机制
为编辑启动菜单进程认证(给grub设置密码,当用户进入grub编辑界面需要输入密码)
为启用内核或操作系统进程认证(用户想进入某个系统需要输入密码)
grub的命令行接口
help:获取帮助列表
help keyword:详细帮助信息
find(hd#,#)/path/to/somefile
root (hd#,#)
kernel /path/to/kernel_file:设定本次启动用到的内核文件;额外还可以添加许多内核支持使用的cmdline参数,内核的所有参数文件至/usr/share/doc/kernel-doc-2.6.32/Documentation
如:max_loop=100 selinux=0(关闭selinux) init=/bin/bash启动的程序
initrd /pah/to/initramfs.img:设定为选定内核提供额外文件的ramdisk
boot:引导启动选定的内核
这一段过程也是当grub.conf文件损坏或丢失的修复过程
识别硬盘设备:
hd(hd#,#)
hd#:磁盘编号,用数字表示,从0开始编号代表的第一块硬盘
#:分区标号,用数字表示,从0开始编号代表第一个分区
(hd0,0)第一块硬盘的第一个分区
手动在命令行接口启动系统
grub>root (hd#,#)
grub>kernel /vmlinuz-2.6.32-642.el6.x86_64 ro root=/dev/device(此分区是“/”文件系统所在分区)
grub>initrd / initramfs-2.6.32-642.el6.x86_64.img
grub>boot
grub.conf配置文件
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/mapper/vg0-LogVol00
# initrd /initrd-[generic-]version.img
#boot=/dev/sda //告诉boot所在的磁盘位置
default=0 //设定默认启动的titile的编号,从0开始
timeout=5 //等待用户选择的超时市场,单位是秒
splashimage=(hd0,0)/grub/splash.xpm.gz //grub的背景图片
hiddenmenu //隐藏菜单
password –md5 加密后的密码 //设定grub密码
title CentOS (2.6.32-431.el6.x86_64) //内核标题或操作系统名称,字符串,可自由修改
root (hd0,0) //内核文件所在的设备对grub而言所有类型硬盘一律为hd;hd#,#表示第n个磁盘,最后的0表示对应磁盘的分区,格式为(hd#,#)
kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=/dev/mapper/vg0-LogVol00 rd_NO_LUKS.UTF-8 rd_LVM_LV=vg0/LogVol00 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet //内核文件路径,及传递给内核的参数
initrd /initramfs-2.6.32-431.el6.x86_64.img //ramdisk文件路径
password –md5 密码串 //启动内核输入密码
grub加密
grub-md5-crypt命令(此命令是个交互式,输入明文密码,输出加密密码)
或
openssl paswwd –salt “abc” -l abc指的是盐指定任意字符即可
破解root口令(5,6版本的系统)
启动系统,设置其运行级别为1,也就是所谓的单用户模式(当然grub没有设置密码,如果你不行其他人通过此方式修改root密码,可以为grub加个密码)
进入单用户模式:
1、编辑grub菜单(选定要编辑的title,之后使用e命令)
2、在选定的kernel后附加 1 | s |S |single 都可以进入单用户模式
3、在kernel所在行,键入b命令,启动系统进入单用户模式
grub的安装
安装grub的第一种方式
grub-install
安装grub stage1和stage1_5到/dev/sda1磁盘行(硬盘的第一个分区,通常为boot目录),并赋值grub相关文件到/boot/目录下
grub-install --root-directory=dir(通常为boot目录的父目录) /dev/sda (boot所在的磁盘)
安装grub的第二种方式
在命令下执行grub命令,会打开一个交互式的界面等待用户输入命令
grub>root (hd#,#) //指定内核所在分区安装grub
grub>setup (hd#)
系统裁剪(自制linux)
1、分区并创建文件系统
fdisk /dev/sdb 分两个必要的区,一个挂载boot,一个挂载sysroot,将分区格式化ext4格式的文件系统
2、挂载
mkdir /mnt/{boot,sysroot}
mount /dev/sdb1 /mnt/boot
mount /dev/sdb2 /mnt/sysroot
3、安装grub
grub-install --root-directory=/mnt /dev/sdb
4、复制内核和intramfs文件
cp /boot/vmlinuz-2.6.32-642.el6.x86_64 /boot/initramfs-2.6.32-642.el6.x86_64.img /mnt/boot/
5、创建grub.conf文件
vim /mnt/boot/grub/grub.conf
default=0
timeout=3
title my linux
root (hd0,0)
kernel /vmlinuz-2.6.32-642.el6.x86_64 root=/dev/mapper/vg0-root root=/dev/sda2 selinux=0 init=/bin/bash
initrd /initramfs-2.6.32-642.el6.x86_64.img
6、创建根下面所需要的目录
mkdir –-pv/mnt/sysroot/{etc,lib,lib64,bin,sbin,boot,home,var
/log,usr/{bin,sbin},root,tmp,var,usr,proc,sys,dev,mnt,media}
7、复制bash和相关库文件
这里使用脚本完成,脚本内容如下:
#!/bin/bash
#
target=/mnt/sysroot
clearCmd() {
if which $cmd &> /dev/null; then
cmdPath=`which --skip-alias $cmd`
else
echo "No such command"
return 5
fi
}
cmdCopy() {
cmdDir=`dirname $1`
[ -d ${target}${cmdDir} ] || mkdir -p ${target}${cmdDir}
[ -f ${target}${1} ] || cp $1 ${target}${cmdDir}
}
libCopy() {
for lib in `ldd $1 | grep -o "/[^[:space:]]\{1,\}"`; do
libDir=`dirname $lib`
[ -d ${target}${libDir} ] || mkdir -p ${target}${libDir}
[ -f ${target}${lib} ] || cp $lib ${target}${libDir}
done
}
while true; do
read -p "Enter a command: " cmd
if [ "$cmd" == ‘quit‘ ] ;then
echo "quit"
exit 0
fi
clearCmd $cmd
[ $? -eq 5 ] && continue
cmdCopy $cmdPath
libCopy $cmdPath
done
执行脚本移植需要用到的命令如mount,umount,ifconfig,ls,pwd,route,ip,vim等等
系统配置文件丢失修复
系统在引导期间,很重要的一个而过程就是init进程读取其配置文件/etc/inittab,启动系统基本服务程序及默认运行级别的服务程序完成引导,如果/etc/inittab误删除或修改错误,Linux将无法正常启动,此时,至于通过救援模式才可以解决此类问题,分两种情况
有备份文件的恢复方法:
进入救援模式,切到根下去(chroot /mnt/sysimage) ,直接将备份文件拷贝到原目录下即可,如:cp /etc/inittab.bak /etc/inittab
没有备份文件的恢复方法:
如果一些配置文件丢失或软件误删除,且无备份,可以通过重新安装软件包来恢复,首先查找到/etc/inittab属于哪一个rpm包
chroot /mnt/sysimage
rpm –qf /etc/inittab
initscripts-9.03.53-1.el6.centos.x86_64
之后挂载光盘,然后在安装initscripts-9.03.53-1.el6.centos.x86_64包
rpm –ivh –replacepgks /media/Packages/initscripts-9.03.53-1.el6.centos.x86_64
如果只提取/etc/inittab文件进行恢复,可以在挂载光盘后执行命令
rpm2cpio /media/Packages/initscripts-9.03.53-1.el6.centos.x86_64 |cpio –id
cp ./etc/inittab /etc/inittab
注意:此命令执行时不能将文件直接恢复至/etc/目录,只能提取到当前目录下,且恢复的文件名称所在路径要写完整的路径,提取文件成功后,将其复制到根分区所在的/mnt/sysimage目录下相应位置即可
内核版本
uname命令
命令格式:uname [OPTION]..
选项
-n:显示节点名称(主机名)
-r:显示内核版本号
-a:显示所有信息
-s:显示内核名称
-m:显示硬件平台
内核模块命令
lsmod :显示由核心已经装载的内核模块
显示的内容来自于/proc/modules文件
modinfo显示模块的详细描述信息
命令格式:modinfo [ -0 ] [ -F field ] [ -k kernel ] [ modulename|filename... ]
选项
-n:只显示模块文件的路径
-p:显示模块参数
-a:author作业
-d:description描述
-l:license
示例:
modinfo ext4
modprobe装载或卸载内核模块
modprobe [ -r ] [ -v ] [ -n ] [ -i ] [ modulename... ]
选项
-r:卸载模块 modprobe -r mod_name
rmmod
rmmod modulesname
示例:
rmmod ext4
insmod 指定模块文件,不能自动解决依赖模块,必须指定绝对路径
insmod [ filename ] [ module options... ]
insmod `modinfo –n ext3`
/proc目录
刚刚提过/proc/modules来查看内核装载的模块,/proc目录我们最初的文件系统结构当中也讲过,该目录是系统与内核交互的一个伪文件系统接口,/proc下的每个文件名都是内核参数,目录名为内核参数节点信息
/proc/sys
sysctl命令用于查看或设定此目录中诸多参数
sysct l –a 查看当前运行中的内核所有参数及值
sysctl –w path.to.parameter=value
sysctl –w kernel.hostname=xiao.com 修改内核参数,立即生效但不能永久生效要想永久生效必须将参数写到配置文件/etc/sysctl.conf中
echo “value”> /proc/sys/path/to/parameter
ehco “xiao” > /proc/sys/kernel/hostname
sysctl –p 通过读取配置文件设置参数
常用的几个参数
net.ipv4.ip_forward 路由转发
kernel.hostname 主机名
vm.drop_caches 缓存 0为不清理缓存,1为清理缓存
net.ipvr.icmp_echo_ignore_all 0开启ping功能,1禁止ping功能
/sys目录
sysfs:为用户使用的为文件系统,输出识别出硬件设备的相关属性信息,也有内核对硬件特性的设定信息,有些参数是可以修改的,用于调整硬件工作特性
udev通过此路径下输出的信息动态为各设备创建所需需设备文件,udev是运行用户空间程序
专用工具udevadmin,hotplug
udev为设备创建设备文件时,会读取其实现定义好的规则文件,一般在/etc/udev/rules.d及、usr/lib/udev/rules.d目录下
ramdisk制作
ramdisk是一个虚拟的根文件系统,这个虚拟的根文件系统在/boot目录下以init开头的文件,他的特点是能够通过Boot Loader程序将其将在到内存当中,然后解压缩并在内存模拟一个根文件系统,这个根文件系统能够提供一个可以运行的程序,通过该程序可以加载在启动过程当中所需要的模块如(RAID、LVM、SCSI),加载完成,会协助内核启动/sbin/init程序来执行后续的启动,那么如何去制作一个ramdisk呢
在CentOS5之上,是通过mkinitrd命令来进行制作,在Centos6之后用dracut命令来制作ramdisk,具体如下:
1、为当前正在使用的内核重新制作ramdisk文件
mkinitrd命令
mkinitrd /boot/iniramfs-$(uname –r).img $(uname –r)
dracut命令
2、制作好之后通过file命令查看initramfs文件,得知是一个gizp的要文件,使用zcat initramfs通过过管道送过cpio进行接压缩查看里面的内容,展开之后发现其实就是一些类似根文件系统目录结构
zcat initramfs-2.6.32-642.el6.x86_64.img | cpio -id 解开
find . | cpio -o –H newc --quiet > gzip -9 /boot/myramdisk.img 归档
内核编译
首先想到的是为什么要编译内核,我们知道内核里包含了可以让硬件设备与软件发挥功能的信息,如果内核里面没有这些设备等信息,系统不会完整的工作的,那我们是不是可以一次性的将所有功能模块编译到内核中去,这样就可以保持目前所有的硬件设备了,如此一来,内核文件大小也变大了不少,而且有些根本不需要的东西也编译进来了,适得其反,所以我们是有选择性的进行编译,对需要的东西就行编译。
需要编译内核的情况有一下几种
1、有新的功能需求,如支持虚拟化
2、原来的内核非常臃肿,想对内核进行简化
3、升级模块修复bug用来提高稳定性
4、定制系统
5、纯属个人学习内核编译使用
在编译内核之前需要充分熟知硬件设备信息,系统平台的相关信息,准备好软件开发环境及内核源代码
- 获取硬件设备信息
cpu
cat /proc/cpuinfo
lscpu
x86info –a
lspci
lsusb
lsblk
- 开发环境准备
安装开发包组
Devlopment Tools Server Platform Development
- 获取源代码
ftp上获取内核源代码
- 内核功能的选择
make menuconfig
[ ]不启动此功能
[M]编译成模块
[*] 编译成核心
注意:要保存退出,所有选定的设置会保存在.config隐藏文件中
- 编译内核步骤
首先下载所需要的内核源代码
通过ftp上资源进行下载或者通过网络下载www.kernel.org
- 解压缩源代码文件到指定目录
tar xf linux-3.18.41.tar.xz -C /usr/src/
- 将解压缩后生成的目录新建一个链接
cd /usr/src
ln -sv linux-3.18.41/ linux
- 复制系统的内核配置模版文件到新内核目录下(文件在/boot目录下有一个config开头的文件)
cp /boot/config-2.6.32-642.el6.x86_64 .
- 选定配置
make help 获取make命令的帮助信息
make config 遍历每个选项
make menuconfig 打开文本串口,配置内核选项(这里需要注意的是,有些小伙伴喜欢用远程工具如xshell这时就需要注意了窗口最好最大化,其他使用screen命令打开一个新串口,以免编译到一遍是远程桌面断开)
make allnoconfig 所有选择均不选择,执行结果将会保存在配置文件.config中
- 编译
make -j # #表示数字,指多线程编译
- 安装模块
make modules_install
- 安装内核
make install
至此内核编译的过程就完成了,只需要重新启动系统,选择自己所编译的内核进入系统即可
编译内核扩展
make clean :保留.config配置文件,删除其他编译生成的所有文件
make mrproper :删除编译生成的所有文件,包括.config文件
make distclean:相当于mrproper 以及删除编译器备份及补丁文件
make gconfig Gnome桌面环境使用,需要安装图形开发库
make xconfig KDE桌面环境使用,需要安装图形开发库
make defconfig 基于内核为目标平台提供的默认配置进行配置
make allyesconfig 所有选项均回答为yes
make allnoconfig 所有选项均回答为no
1、只编译其中部分代码
只编译某个子目录下的相关代码
make dir/ make driver/net/
2、只编译部分模块
make m=driver/net/
3、只编译某一个模块
make driver/net/pcnet32.ko
4、将编译完成的结果放置于指定的目录中
make o=/tmp/kernel
5、交叉编译
make ARCH=arch_name
获取特定目标平台的使用帮助
make ARCH=arch_name help
make ARCH=arm help