做者:张华 发表于:2013-01-27 ( http://blog.csdn.net/quqi99 )html
运行一个linux系统须要三项内容:
1,kernel, 内核,一些核心的代码块,如进程管理,它要求体积很小。
2,initrd, 进入系统所需预告加载的硬件驱动module的一个最小集。当GRUB加载kernel时,kernel会在内存中将initrd文件mount到rootfs上激活,而后kernel照着initrd中的init一步一步地加载驱动。在initrd文件中所放入的模块,必须是与操做系统同一版本kernel所编译的模块。init脚本的工做流程是:
initrd的参考文档可见:
1) Linux initial RAM disk (initrd) overview, http://www.ibm.com/developerworks/linux/library/l-initrd/index.html
2) NTTdocomo-openstack / baremetal-initrd-builder, https://github.com/NTTdocomo-openstack/baremetal-initrd-builder
2.1, nash指令(一个文件小,内置了一些实用的指令)
2,2 挂载主要的文件系统, 并创建设备文件所需的文件系统
mount -t proc /proc /proc
mount -t sysfs /sys /sys
2.2.1,procfs映射着内存中的一个虚拟目录,用于提供硬件、进程的实时信息,会随时变更。linux为保证稳定性,不容许访问/proc下的文件,root用户也不例外。
2.2.2, sysfs也映射着内存中的一个虚拟目录,用于硬件信息的分类, sys目录的每个文件都只有一个字符为内容来作开关的。
2.2.3, tmpfs也映射着内存中的一个虚拟目录,内存中的文件系统。想要速度快时,能够选择在内存创建tmpfs类型的文件系统,由于它都将建在内存中。
例如在内存中创建了一个tmpfs分区并挂载到/mnt/tmpfs目录 :mount -t tmpfs -o size=50M tmpfs /mnt/tmpfs/
[root@zhanghua proc]# df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 50M 0 50M 0% /mnt/tmpfs
2.2.4, /dev/shm,它是tmpfs的一种变种,tmpfs全部的内容所放在内存中,而/dev/shm在内存与文件系统有个映射,硬盘和内存中都会有这内容。
速度快,能存大于内存的文件,但重启以后,内容会消失。
下面显示在/dev/shm中创建文件与在普通ext4文件系统建文件的速度比较:
[root@zhanghua proc]# time dd if=/dev/zero of=/dev/shm/test.file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.0395221 s, 2.7 GB/s
real 0m0.075s
user 0m0.001s
sys 0m0.041s
[root@zhanghua proc]# time dd if=/dev/zero of=/bak/test.file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.0647526 s, 1.6 GB/s
real 0m0.090s
user 0m0.001s
sys 0m0.066s
2.2.5,devfs, 全部的device都会在/dev目录创建一个对应的设备文件.
缺点是例如即便打印机没连在计算机上,/dev/printer文件也会存在,这样会形成在intrd阶段的设备过多,因此devfs正在被udev所取代
例如要用光驱时,需先在linux与光驱之间经过 mount /dev/cdrom /mnt/命令作关联
2.2.6, udev, udev能够放在/sys目录下,不须要将全部未使用的文件创建设备文件,再也不须要major number和minor number,当硬件被加载时可执行用户设置的script。
例如,若是/dev/cdrom是被udev创建的,而非devfs,那么当光驱被拨除时,/dev/cdrom文件就会消失。
2.2.7,/proc/PID文件,第一个进程都会对应这要闰个文件
2.2.8,/proc/partitions用来表示检测到的硬盘信息, major字段表示SCSI controller的slot ID,minor字段表示分区ID。
#[root@zhanghua proc]# cat /proc/partitions
major minor #blocks name
8 0 488386584 sda
8 1 82051956 sda1
2.2.9, /sys/block,块设备
#[root@zhanghua proc]# cat /sys/block/
loop0/ loop1/ sda/ sr0/
2.2.10, /dev/pts ( pseudo terminal slave) 副虚拟终端,其目录的文件都是由ptmx(主虚拟终端)产生的,它们是父子关系。当用ssh联机到localhost本地端以后,就会在
/dev/pts目录下产生一个叫作"0"的文件,当别的console也利用ssh联到这台机器时,就会出现“1“.
[root@zhanghua proc]# ps -ef|grep ssh
hua 11186 3068 0 16:01 pts/0 00:00:00 ssh hua@localhost
hua 11195 11187 0 16:01 ? 00:00:00 sshd: hua@pts/3
如上,当一个用户以ssh登陆以后,该用户就分到一个ptmx所赋予的pts资源(pts/3),因此说ssh使用的是虚拟终端,不是真正的tty接口。telnet用的则是真正的tty接口。
2.2.11, /dev/mapper,若是使用LVM后,linux要和硬盘打交道时再也不直接使用/proc/partitions下的硬盘设备,而是使用/dev/mapper下的设备再去中转。
# ls -l /dev/mapper/*
brw-rw---- 1 root disk 253, 0 jan 27 16.16 /dev/mapper/vg0-lv0
# cat /proc/partitions
major minor #blocks name
8 0 17528 sda
253 0 1111 dm-0
3,创建最初所需使用的设备文件
设备文件使用mknod指令创建,mknod指令用来创建字符(character)或块(block)文件。
例:mknod /dev/tty1c41, 创建一个名为tty1的设备文件,c表示是字符文件,major=4, minor=1
4,加载相关模块
5,切入image所指示的硬盘中实体操做系统. (rescue mode是直接经过kernel加载initrd进入单纯的内存开机的虚拟操做系统)
5.1, mkrootdev -t ext4 -o defaults.ro hda1, 即nash指令会将GRUB中所设备的root=xxx中的xxx路径先创建好
5.2, mount /sysroot, 将GRUB中的root路径mount到initrd中的/sysroot下。
5.3, switchroot这个nash指令将initrd中的/sysroot文件系统切换成/rootfs,从而切换到了硬盘中的文件系统。
3,image, 操做系统的image文件系统,当initrd被加载后,必须为用户与文件系统牵线。
4, init进程,在切入到用户操做系统以后,首先执行linux的init进程(pid=1), init进程再去加载/etc/rc.d/init.d/functions从而启动服务。
关于启动级别与init进程的事儿,也可参见个人另外一博文件,Linux的运行级别与解决开机故障一例 ( by quqi99 ), http://blog.csdn.net/quqi99/article/details/7436926
5, 系统管理
5.1, 查看CPU信息 cat /proc/cpuinfo
5.2, 查看内存, cat /proc/meminfo 或者 free -m
5.3, 查看usb, lsusb
5.4, 查看PCI, lspci
5.5, 查看开机日志, dmesg |grep -i error
本文讲的是如何编译kernel,接下来也会研究如何制做initrd与image.
最好使用普通用户执行下面全部操做。
1,下载内核源码
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
用git tag查看版本,将并代码切换到v3.8-rc5下, git checkout v3.8-rc5
2,配置内核(有点相似于./configure), 配置前先安装一个依赖包, sudo yum install ncurses-devel,
make menuconfig
说明一下,内核的配置项是三选一,yes, no, 或module。yes, no意味着直接将该特性编译或不编译到内核中,module意味着以模块形式编译,模块意味着你开机会能够通modprobe命令动态加载或卸载。
我在这里选择的默认配置,生成的配置位于根目录下的.config文件之中。
若是你在一个老的配置文件上更改配置的话,能够用make oldconfig命令比较与以前的配置文件的差别来验证你配置的正确性。
3,执行make命令编译,
make
说明一下,这条命令实际上已经包括了下面的命令:
1)肯定依赖性 make dep
2)清理编译中间文件,make clean
3)编译内核, make bzImage
4)生成模块, make modules
4, 安装模块,下列命令会将模块自动安装到/lib/modules/3.8.0-rc5/目录下.
sudo make modules_installlinux
5, 安装内核及initrd,人工将arch/x86/boot/bzImage的内核文件拷到/boot目录便可。
sudo cp arch/x86_64/boot/bzImage /boot/vmlinuz-3.8.0-rc5
sudo chmod a+x vmlinuz-3.8.0-rc5git
sudo update-initramfs -u -k version github
sudo update-grub -o /boot/grub/grub.cfg
注意:以vmlinuz-<version>这样命名它。算法
上述三步等价于make install, 但make install在自动执行update grub命令时有时候会破坏你的grub文件,特别对于进行PGP加密过的硬盘。ubuntu
6,「可选」,安装符号表,只有调试时才须要用到。符号表System.map用以将内核符号和它们的起始地址对应起来,调试的时候,若是须要把内存地址翻译成容易理解的函数名和以及变量名,就会颇有用。vim
sudo cp System.map /boot/System.map-3.8.0-rc5
7, 创建initrd文件
sudo mkinitrd --with=ntfs -o /boot/initrd-linux3.8.0-rc5.img 3.8.0-rc5
以上mkinitrd命令是参照现有系统的/etc/modprobe.conf和/etc/fstab文件建立一个全新的initrd, 用--with=ntfs会从/lib/modules/3.8.0-rc5目录将ntfs模块也作到initrd里去。
那如何要从头开始作一个initrd呢?
1) 能够用 sudo zcat initrd-linux3.8.0-rc5.img | cpio -id 命令解压 ( initrd文件是以ext2做为文件系统中,因此能够用mount -o loop initrd.img /mnt命令加载.)
2) 而后将模块ntfs.ko加到相应的目录,如lib/modules/3.8.0-rc5/kernel/fs/ntfs目录
3) 将ntfs.ko模块加到init脚本
4) 从新压缩,find | cpio -co | gzip -9 > initrd-new.img
8, 更新grub, 编译/etc/grub/grub.conf文件,添加下面内容,注意千成不要用update grub命令来更新grub哦,这可能会致使你的双系统没法用。
menuentry 'Fedora,Linux 3.8.0' --class fedora --class gnu-linux --class gnu --class os {
set root='(hd0,msdos9)'
linux /boot/vmlinuz-3.8.0-rc5 root=/dev/sda10 ro quiet splash
initrd /boot/initrd-linux3.8.0-rc5.img
}
也能够在开机时按e进入grub编辑模式,再按e一次进入kernel的设置界面:
grub> root (hd0,msdos9)
grub> kernel /boot/vmlinuz-3.8.0-rc5 ro root=/dev/sda9 acpi=off (注意,kernel在前的grub>光标后必定要空一行)
grub> initrd /boot/initrd-linux3.8.0-rc5.imgcentos
grub> bootbash
9, 下面讲一下用于裸机的image的制做过程,须要将虚拟机磁盘系统(raw, qcow2, vhd等)往Linux识别的ext4格式转换。架构
create raw disk
sudo kvm-img create -f raw /bak/kvmimages/ubuntutemplate.img 8G
install kvm virtual machine
sudo kvm -m 728 -cdrom/bak/kvmimages/ubuntu-11.04-desktop-i386.iso -drivefile=/bak/kvmimages/ubuntutemplate.img -boot d -nographic -vnc :0
use vnc to see: vncviewer192.168.99.100:5900
启动虚机以后安装一些如SSH,cloud-init等软件
sudo apt-get install kvm-pxe
sudo kvm -m 728 -drivefile=/bak/kvmimages/ubuntutemplate .img -boot c -nographic -vnc :0
sudo apt-get install openssh-servercloud-init
sudo rm -rf/etc/udev/rules.d/70-persistent-net.rules #删它,防止添加其余网口
sudo shutdown -h now
调整镜像, 由于openstack只接受ext4文件系统格式,故需将raw格式转化成ext4
root@zhhua:/bak/kvmimages# sudo losetup -f --show /bak/kvmimages/ubuntucapture.img
root@zhhua:/bak/kvmimages# sudo losetup -a
/dev/loop0: [0809]:5770371(/bak/kvmimages/nova.img)
/dev/loop1: [0809]:5770373(/bak/kvmimages/ubuntucapture .img)
root@zhhua:/bak/kvmimages# sudo fdisk-l /dev/loop1
Disk /dev/loop1: 8589 MB, 8589934592bytes
255 heads, 63 sectors/track, 1044cylinders, total 16777216 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes/ 512 bytes
Disk identifier: 0x0009d391
Device Boot Start End Blocks Id System
/dev/loop1p1 * 2048 15286271 7642112 83 Linux
/dev/loop1p2 15288318 16775167 743425 5 Extended
/dev/loop1p5 15288320 16775167 743424 82 Linux swap
显示分区是从扇区(sector)2048开始的,每一个扇区是512个字节,因此是从2048 x 512 = 1048576个字节开始的。记住这个1048576,下面会用到
卸载loop后从新从1048576字节开始挂载:
sudo losetup -d /dev/loop1
sudo losetup -f -o 1048576 /bak/kvmimages/ubuntucapture.img
把这整个分区拷贝到一个新文件就是一个咱们要的ext4文件系统镜像
sudo dd if=/dev/loop1 of=/bak/kvmimages/ubuntutemplate.img
用完loop后记得卸载,sudo losetup -d /dev/loop1
挂载刚建立的ext4根文件系统,修改分区加载表(/etc/fstab),注释或删除之前的,加上“LABEL=my-rootfs / ext4 defaults 0 0”一行,
最后,别忘了运行下列命令将块设备的卷标修改为咱们上面设置的my-rootfs, sudo tune2fs -L my-rootfs /bak/kvmimages/ubuntutemplate.img:
sudo mount -o loop /bak/kvmimages/ubuntutemplate.img /mnt
sudo vi /mnt/etc/fstab
#UUID=98a4bc39-82a9-4d20-abf8-4aef654c1268 / ext4 errors=remount-ro 0 1
UUID=my-rootfs / ext4 defaults 0 0
# swapwas on /dev/sda5 during installation
UUID=3afdd9f7-7e1e-4172-ae32-7407b0559c51none swap sw 0 0
把内核(vmlinuz)和initrd文件拷贝出来以便后面和虚拟机镜像一块儿发布到OpenStack云里。使用完虚拟机镜像后记得卸载(unmount):
sudo cp /mnt/boot/vmlinuz-2.6.38-8-generic /bak/kvmimages/boot/
sudo cp /mnt/boot/initrd.img-2.6.38-8-generic /bak/kvmimages/boot/
sudo umount /mnt
整个过程是,initrc或者initramfs都是一个运行在内存的小根文件系统,它有一个叫init的脚本,作完一些准备工做以后,如加载硬件的驱动,而后会切换到镜像所在的新根文件系统上,下面就是一个intramfs中init脚本的例子:
#!/bin/sh
mount -vt proc proc /proc #不少工具都读proc的数据,故先加载
mount -vt sysfs sysfs /sys #加载内核文件系统
insmod scsi_mod #要切换到镜像的新根文件系统,固然要先加载硬件用的scsi驱动模块
insmod libata
insmod ata_piix
insmod sd_mod
mdev -s 或者echo /sbin/mdev > /proc/sys/kernel/hotplug #可使用busybox的mdev生成动态的udev文件,也可使用hotplug技术在加载模块的时候再加载相应的设备
mount /dev/sda /mnt #加载硬盘,或者直接加到根目录/中
exec switch_root /mnt /sbin/init #经过exec会让镜像中的init进程彻底替换initramfs中的init进程的空间来切换根文件分区
/bin/sh #若是上述切换根文件分区失败,还可使用initramfs的sh进程,不然会panic
因此说,这个镜像应该是linux内核直接能够认的文件系统格式,如ext4, 直虚机使用的文件格式像raw, qrow2等须像如上方式转换到ext4等格式。这样也就能够直接经过dd命令将镜像拷到/dev/sda硬盘中了(gunzip -c /mnt/sda1/hda.img.gz | dd of=/dev/hda conv=sync,noerror bs=64K)
想把整个硬盘备份到外部存储移动硬盘中的话:
1,加载移动硬盘,mount -t vfat /dev/sda1 /mnt/sda1
2,dd备份,dd if=/dev/hda conv=sync,noerror bs=64K | gzip -c > /mnt/sda1/hda.img.gz
3, 恢复,gunzip -c /mnt/sda1/hda.img.gz | dd of=/dev/hda conv=sync,noerror bs=64K
显然, dd的缺点是备份整个硬盘分区,无论它是否是真用了。有个叫再生龙的工具(Clonezilla)就是来克服这个缺点的。下面是它的介绍:
Clonezilla是一个很好的系统克隆工具,它基于Partimage,吸收了Norton Ghost和Partition Image的优势。即不只支持对整个系统进行克隆,并且也能够克隆单个的分区,这种灵活性可能更能适应备份者的须要.支持GNU/Linux的文件系统 ext二、ext三、reiserfs、xfs、jfs和Windows的FAT、FAT3二、NTFS文件系统.Clonezilla支持使用 PXEBoot来进行Multicast克隆.这对于须要克隆大量系统的用户极为有用. Clonezilla 比起Ghost For Linux(简称G4L)有一个很显著的优点就是Clonezilla支持的文件系统格式比G4L多之外Clonezilla只备份数据,而G4L却将整个分区都备份了(即包含空数据),因此G4L将比Clonezilla占用更多的用于存放备份镜像的空间。
或者咱们使用另外一种方式制做OpenStack镜像(即根文件系统),例如linux-0.2.img是一个采用kvm虚机安装的raw格式的镜像,如今将它转成linux内核认识的ext4格式的根文件系统。
1, sudo mkdir -p /mnt/{raw,ext4} && sudo mount -o loop linux-0.2.img /mnt/raw
2, dd if=/dev/zero of=linux-0.2.ext4 bs=1M count=22
mkfs.ext4 linux-0.2.ext4
sudo mount -o loop linux-0.2.ext4 /mnt/ext4
3, sudo cp -r /mnt/raw/* /mnt/ext4/
直接用raw格式的作镜像也是能够的,那样就不须要转换了,glance add name="CentOS-6.4-x86_64" is_public=true container_format=ovf disk_format=raw < CentOS-6.4-x86_64.img
最后,现看一下如何挂载raw和qcow2格式的KVM硬盘镜像
raw格式
对于未分区镜像文件直接使用loop:
mount -o loop image.img /mnt/image
已分区的镜像文件:
若是已知分区的起始位置
mount -o loop,offset=32256 image.img /mnt/image
或者使用losetup + kpartx
losetup /dev/loop0 image.img
kpartx -a /dev/loop0
mount /dev/mapper/loop0p1 /mnt/image
kpartx命令的做用,是让Linux内核读取一个设备上的分区表,而后生成表明相应分区的设备。
kpartx -l imagefile 能够查看一个映像文件中的分区,使用 kpartx -a imagefile 命令后,就能够经过 /dev/mapper/loop0pX (其中X是 分区号)来访问映像。
qcow2格式
对于qcow2格式须要使用qemu-nbd这个工具
modprobe nbd max_part=63
qemu-nbd -c /dev/nbd0 image.img
mount /dev/nbd0p1 /mnt/image
若是是LVM格式的镜像:
vgscan
vgchange -ay
mount /dev/VolGroupName/LogVolName /mnt/image
最后使用结束需释放资源:
umount /mnt/image
vgchange -an VolGroupName
killall qemu-nbd
kpartx -d /dev/loop0
losetup -d /dev/loop0
initrd 的英文含义是 boot loader initialized RAM disk,就是由 boot loader 初始化的内存盘。在 linux内核启动前,boot loader 会将存储介质中的 initrd 文件加载到内存,内核启动时会在访问真正的根文件系统前先访问该内存中的 initrd 文件系统。在 boot loader 配置了 initrd 的状况下,内核启动被分红了两个阶段,第一阶段先执行 initrd 文件系统中的"init or linuxrc",完成加载驱动模块等任务,第二阶段才会执行真正的根文件系统中的 /sbin/init, Linux2.6既支持cpio-initrd,也支持image-initrd,可是cpio-initrd有着更大的优点,在使用中咱们应该优先 考虑使用cpio格式的initrd.
Initrd 的主要用途
linux 发行版必须适应各类不一样的硬件架构,将全部的驱动编译进内核是不现实的,initrd 技术是解决该问题的关键技术。Linux 发行版在内核中只编译了基本的硬件驱动,在安装过程当中经过检测系统硬件,生成包含安装系统硬件驱动的 initrd,是一种便可行又灵活的解决方案。
1.解压 initrd
# file initrd.`uname –r`.img (察看格式,不一样的linux操做系统,这个文件格式也有不一样,这个文件格式多是cpio 也多是ext2)
若是是cpio格式 :
# mkdir /mnt/tmp
# cd /mnt/tmp
# cpio -idmv </tmp/initrd.`uname -r`.img
2 压缩initrd
2.1 mkinitrd
#cd /lib/modules/`uname -r`
#mkinitrd /tmp/initrd.`uname -r`.img `uname -r`
#cd /tmp
#mv initrd.`uname –r`.img initrd.`uname –r`.img.gz
(initrd使用gzip压缩,若是不更名字的话,后面没法解压缩) #gunzip initrd.`uname -r`.img.gz
2.2 cpio
#假设当前目录位于准备好的initrd文件系统的根目录下
第一种方式,老的-c选项,用的是ascii码备份方式.
# find . | cpio -c -o > ../initrd.img
# gzip ../initrd.img
第二种方式,新的.已经测试可用的方式.
#cd /root/busybox-1.15.3/rootfs9260
#find . | cpio -H newc -o > ../initrd_cpio.img
#cd ../
#cp initrd_cpio.img initrd_cpio_bk.img -f
#gzip initrd_cpio.img -f
#/home/u-boot-1.1.5/tools/mkimage -A arm -T ramdisk -C none -O linux -a 0x600000 -e 0x600000 -d initrd_cpio.img.gz /home/ramdisk.uboot
#ls /home/ramdisk.uboot -al
上面cpio命令的 -H 选项指定打包文件的具体格式,要生成initramfs,只能用newc 格式,若是使用其余格式,
内核会打出这样的出错信息:Unpacking initramfs...<0> kernel panic - not syncing: no cpio magic
或者出现:Unpacking initramfs...<0>Kernel panic - not syncing: bad gzip magic numbers。 若是采用了-c旧的ascii码备份方式,则内核会按照ramdisk的方式加载根文件系统。
若是你在编译内核时选上了RAM block device support (在device drivers -> block devices里),
也能够启动成功,但这就失去了cpio-initrd的意义了!。
再就是注意cpio-initrd的初始进程是 “/init”,ramdisk方式初始进程是"/linuxrc"。
另外若是采用cramfs格式的根文件系统,也需在编译内核时选上RAM block device support。
2.3 gen_init_cpio
获取 gen_init_cpio,工具 ,gen_init_cpio是编译内核时获得的,
在内核源代码的 usr 目录下,咱们能够经过 如下步骤获取它,进入内核源代码 执行 :
# make menuconfig
# make usr/
这样即编译好gen_init_cpio,
gen_initramfs_list.sh 在内核源代码的 script 目录下,
将这两个 文件 copy 到 /tmp 目录下,/tmp/initrd 为 解压好的 initrd 目录,执行如下命令 制做initrd :
#制做initrd :
# gen_initramfs_list.sh initrd/ > filelist
# gen_init_cpio filelist >initrd.img
# gzip initrd.img
# mv initrd.img initrd-'uname –r’.img
只有用这个方式压缩的initrd ,在Linux系统重启的时候才能 一正确的文件格式 boot 起来,也能够用
这种方式修改安装光盘的initrd文件 而后 进行系统安装。
3. 如何在 initrd 中添加新的驱动,以 ahci.ko 为例
3.1 gen_init_cpio
# cp initrd-‘uname –r‘.img /tmp/initrd;cd /tmp/initrd
# cpio –ivdum < initrd-‘uname –r’.img;
# mv initrd-‘uname –r’.img ../
# cd /tmp/initrd
# vim init加上一行 insmod /lib/ahci.ko
# cp ahci.ko lib/
# cd /tmp
# gen_initramfs_list.sh initrd/ > filelist
# gen_init_cpio filelist >initrd.img
# gzip initrd.img
# mv initrd.img initrd-‘uname –r’.img
至此,新的initrd文件initrd-‘uname –r’.img中就包含了ahci的驱动程序了 ,这种方式是最简单有效的。
3.2 mkinitrd
(1) Add “alias scsi_hostadapter ahci” at /etc/modprobe.conf
(2) copy ahci.ko to “/lib/module/$(kernel-version)”/kernel/drivers/scsi”
(3) mkinitrd initrd.img ‘uname -r’
至此,新的initrd文件initrd-‘uname –r’.img中就包含了ahci的驱动程序了 .
#释放cpio格式的initrd:
mv initrd.img imitrd.img.gz
gunzip initrd.img.gz
cpio -i --make-directories < initrd.img
#释放centos6.2系统的initramfs.img
1."gunzip initrd.img-2.6.27-7-generic.gz",获得一个未压缩的initrd.img-2.6.27-7-generic
2. ”cpio -iv <initrd.img-2.6.27-7-generic",提取成功
#制做cpio格式的initrd(新2012年使用过的)
# cd /root/busybox-1.15.3/rootfs9260 # find . | cpio -H newc -o > ../initrd_cpio.img
#制做cpio格式的initrd(2009年制做的LFS的方式):
dd if=/dev/zero of=/tmp/rootfs bs=1k count=35000
losetup /dev/loop0 /tmp/rootfs
mkfs.ext2 –F –i 2000 /tmp/rootfs
mkdir /tmp/loop
mount –o loop /tmp/rootfs /tmp/loop
#而后将刚才创建的基本系统拷贝到/tmp/loop
cp /lfs/* /tmp/loop –arfp
find . | cpio –o –H newc | gzip –c > /tmp/initrd.img
红帽(Red Hat)从Enterprise Server 6.2 开始,启动镜像文件initrd.img 开始改用xz 工具进行压缩,这与以往版本是有区别的。
1、启动镜像initrd.img 文件
类RedHat 系统从vmlinuz 核心引导后,会读取initrd.img 启动镜像。该文件中包含驱动模块等信息,是很是重要的文件。不一样版本使用的格式不一样。
1.RHEL 4.0 版本
采用ext2 文件格式镜像,再经过gzip 压缩:
2.RHEL 5.0 版本
采用cpio 打包镜像,再经过gzip 压缩:
3.RHEL 6.2 版本
RHEL 6.0 - 6.2 都采用与RHEL 5.0 相同的格式进行打包,但从6.2版本开始,改用LZMA 进行压缩。详见:Release Notes for Red Hat Enterprise Linux 6.2 Edition 2。
以下:
※ 注意,若在低于RHEL 6.2 版本下执行file 命令,可能没法识别LZMA 压缩格式:
这时,可把file 软件包升级到5.04-13.el6 便可。
2、xz 工具简介
xz 工具是LZMA 压缩算法的一个实现。具体可见:Wikipedia
可见,Windows 下可以使用7-Zip 打开.xz 文件。LZMA 算法比Gzip 算法压缩率更高。几个参数:
3、手动修改initrd.img 文件
解压:
压缩:
3、补充tar.lzma
因为LZMA 具备优秀的压缩率及占用资源少的特色,愈来愈多的工具采用lzma进行打包,后缀名为:tar.lzma。
对于Fedora 11 及之后的版本,可使用下面的命令操做:
压缩
解压:
若是是CentOS 5.3 等老版本,须要安装独立的lzma 工具或用xz 进行:
压缩:
解压(两个方式均可以):
光盘中的initrd.img
位置isolinux/initrd.img
1 解压缩
file后发现是xz文件
将initrd.img更名,更名为Initrd.img.xz
为何要更名?由于不更名xz会叫唤,说你胡塞给我什么文件啊?我不解压缩
file initrd.img
mv initrd.img initrd.img.xz
unxz initrd.img.xz
解压缩完成。
结果:生成一个initrd.img,和原始文件比,这个文件是个cpio后的文件
2 cpio解出来
file initrd.img(第一步解压缩出来的名字)
发现是cpio
cpio -i -d < initrd.img
结果:生成全部文件系统,主要是usr, etc, lib等目录
2.6内核中的initrd.img采用cpio压缩,再也不是2.4内核使用的ext2格式,没法使用mount -o loop 挂载。须要使用gunzip解压缩,而后再使用cpio解包
cp /boot/initrd-***.img initrd.img.gz
gunzip initrd.img.gz
mkdir initrd
mv initrd.img initrd
cd initrd
cpio -ivmd ../initrd.new.img
gzip ../initrd.new.img
再将其更名拷贝至/boot目录,重启就能够观察修改后的效果。重启后没法成功引导。这是由于生成的initrd.img不对。解决以下:
生成initrd
find . | cpio -o -H newc | gzip > /mnt/sda1/boot/initrd.img-2.6.18-4-686
(注:-H newc 是必须的,不然内核会认为是ramdisk,而不是initramfs)
Extract
gunzip < /boot/initrd.img | cpio -i –make-directories
Repack
find ./ | cpio -H newc -o > initrd.cpio
gzip initrd.cpio
mv initrd.cpio.gz initrd.img
Uncompress:
mkdir initrd
cd initrd zcat ../initrd.img | cpio -idmv
Compress:
find . | cpio -o -c | gzip -9 > ../initrd.img
initrd.img解压:
[root@CentOS5 ~]# mkdir /usr/src/initrd
[root@CentOS5 ~]# cp /boot/initrd-2.6.18-308.el5.img /usr/src/initrd
[root@CentOS5 ~]# cd /usr/src/initrd
[root@CentOS5 initrd]# ls
initrd-2.6.18-308.el5.img
[root@CentOS5 initrd]# mv initrd-2.6.18-308.el5.img initrd-2.6.18-308.el5.img.gz
[root@CentOS5 initrd]# gunzip initrd-2.6.18-308.el5.img.gz
[root@CentOS5 initrd]# cpio -i -d < initrd-2.6.18-308.el5.img
[root@CentOS5 initrd]# rm -rf initrd-2.6.18-308.el5.img
[root@CentOS5 initrd]# ls
bin dev etc init lib proc sbin sys sysroot
initrd.img打包:
[root@CentOS5 initrd]# find . -print|cpio -o -H newc > ../initrd-2.6.18-308.el5.img
[root@CentOS5 initrd]# cd ..
[root@CentOS5 src]# gzip -9 initrd-2.6.18-308.el5.img
[root@CentOS5 src]# mv initrd-2.6.18-308.el5.img.gz initrd-2.6.18-308.el5.img
[root@CentOS5 src]# ls
initrd-2.6.18-308.el5.img
*initrd.img打包也可采用以下命令:
[root@CentOS5 initrd]# find . | cpio --quiet -H newc -o | gzip -9 -n > ../initrd-2.6.18-308.el5.img.gz
[root@CentOS5 src]# mv initrd-2.6.18-308.el5.img.gz initrd-2.6.18-308.el5.img
[root@CentOS5 src]# ls
initrd-2.6.18-308.el5.img
Ubuntu的initrd.img能够在/boot中找到,一般文件名后面还跟有很长的一串版本号。
为了保险起见,不直接操做原文件,而是把它复制到本身的家目(home)录中。若是你是用root账号登陆的,家目录就在/root中,若是是用wsxx登陆的,家目录通常就在/home/wsxx中,一般登陆以后自动就到了家目中。咱们把initrd.img复制但家目中进行解压:
cp /boot/initrd.img-2.6.15-ubuntu-r6 ./initrd.img.gz
上面这个命令把/boot区中的文件复制到当前目录,并改名为initrd.img.gz。一方面改为短文件名好一点好操做,另外一方面加上gz的后缀更清楚代表它本来就是一个gzip压缩出来的文件。http://www.ccthere.com/article/825480
而后解压:
gunzip initrd.img.gz
也能够:http://www.ccthere.com/article/825480
gzip -d initrd.img.gz
二者结果是相同的,都是在当前目录获得一个解压后的initrd.img,原来的initrd.img.gz被删除掉了(这也许是linux整洁的优势)。
如今这个更大的initrd.img要用cpio解开,成为一系列目录和文件。为了避免与当前目录中现有的文件搞混,咱们有必要新建一个目录,把initrd.img解压到新目录中去。未来把里面的文件修改好以后,还要把全部的目录文件再打包起来:http://www.ccthere.com/article/825480
mkdir initrd #创建目录
cd initrd #进入目录
cpio -i -d < ../initrd.img #解开上层目录中的initrd.img http://www.ccthere.com/article/825480
由于已经进入到initrd中,../initrd.img表示上层目录中的initrd.img。
如今就能够看到initrd中各目录中有不少新的目录和文件了。在这里咱们能够窥视到ubuntu是如何装配起来的。能够对其中的内容进行修改了。
http://www.ccthere.com/article/825480
修改文本文件没有什么好多说的了。
修改以后,就是压缩回去,用它来启动,检验是否能够正常启动,是否达到预期的修改目的。先用cpio打包:
http://www.ccthere.com/article/825480
find . | cpio -o -H newc > ../myinitrd.img #打包当前目录中的全部目录和文件,到上层目录中的myinitrd.img
cd .. #回到上层目录
gzip -9 myinitrd.img #gzip的最高级压缩http://www.ccthere.com/article/825480
获得的myinitrd.img.gz就是新的Ubuntu启动文件了。
作到这里,要有必要停下来看看一看,比较一下从新压缩以后的文件,是否和原来的initrd.img.gz差很少大小?都应该是4M多的文件。若是文件大小相差太多,可能就有问题。我用Ubuntu文件解压后在压缩回来,用不一样的文件名,最后比较,大小彻底一致,内心就踏实了。
http://www.ccthere.com/article/825480
再用Gentoo的initramfs文件进行一样方法的操做,2M多的文件解压再压缩回来,只剩下不到1K了,本身也不相信这是对的。
==================== End