版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、(一)hello world 一、initramfs是什么二、构建第一个initramfs:hello world 从C语言开始,学习计算机编程语言的第一个程序几乎都是hello world,因此我们也构建一个最简单的hello world式的initramfs,以说明initramfs的基本构建方法。 initramfs的灵魂是init文件(或者叫程序,因为它会被内核第一个执行),我们先写一个简单的init程序,它会在内核的console中打印出经典的hello world信息。 hello.c: #include <stdio.h> #include <unistd.h&
2、gt; int main(int argc,char argv) printf("hello world, from initramfs.n"); sleep(9999999); return 0; 其中的sleep()函数语句是为了避免执行时内核很快打出panic的信息,并非功能上的需要。 接着把hello.c编译成静态连接程序: gcc -o hello_static -static -s hello.c 命令行中的-s参数表示编译后的程序不包含调试定位信息,目的是减少编译出来的程序文件的大小。 再创建一个initramfs的构建源文件目录image,把hello_st
3、atic程序拷入这个目录,并改名为init。 在image目录下,创建一个dev/console的设备文件,否init程序无法在内核console中输出信息: mknod -m 600 dev/console c 5 1 注意,执行这个命令需要有root权限。 好了,现在可以设置内核配置参数,进行initramfs的构建了: 在general setup配置目录下的initramfs sources配置项下输入image的路径名,比如我的路径就是/home/wyk/initramfs-test/image。因为我们的init程序是ELF格式的,所以内核需要支持ELF的可执行文件,否则启动这个i
4、nit程序会失败。在内核的 Executable file formats配置目录下,选择 kernel support for ELF binaries,则可使内核支持ELF格式的可执行文件。其他内核配置参数根据实际需要设置即可,不过,为了减少内核编译时间,可参考这篇文章设置一个最简单的内核配置。 内核配置参数设置完成后,按常规的内核编译方法进行编译,initramfs就自动连接到编译好的内核映像文件中了。 三、试验环境搭建 试验initramfs需要经常重启系统,所以使用CPU模拟器是不错的选择。我们可以选用qemu,它支持直接启动linux内核,无需在模拟器中安装OS。从方便使用的角度考
5、虑,我们采用qemu launcher设置qemu的各项参数,它的安装可参考。 在qemu launcher的linux配置标签中,打勾直接启动linux,然后在下面的文本框中填上刚才编译好的内核映像文件的路径名。因为qemu的运行还需要设置硬盘映像文件,所以还需要在左边的配置标签中新建一个硬盘映像文件,但实际上我们并不使用硬盘。 配置好qemu的参数后,点击launcher按钮,内核就开始在qemu中运行了。内核输出一堆内核运行信息后,最后打出了 hello world, from initramfs. 哈哈,我们构建的initramfs已经能够正常工作了!(二)initramfs的前世今生
6、 四、什么是rootfs和ramfs 所有的2.6版本linux内核都有一个特殊的文件系统rootfs,是内核启动的初始始根文件系统,initramfs的文件会复制到rootfs。如果把initramfs比作种子,那么rootfs就是它生长的土壤。大部分linux系统正常运行后都会安装另外的文件系统,然后忽略rootfs。 rootfs是ramfs文件系统的一个特殊实例。ramfs是一种非常简单的文件系统,是基于内存的文件系统。ramfs文件系统没有容量大小的限制,它可以根据需要动态增加容量。 ramfs直接利用了内核的磁盘高速缓存机制。所有的文件的读写数据都会在内存中做高速缓存(cache)
7、,当系统再次使用文件数据时,可以直接从内存中读写,以提供系统的I/O性能。高速缓存中的写入数据会在适当的时候回写到对应的文件系统设备(如磁盘等)中,这时它的状态就标识为clean,这样系统在必要时可以释放掉这些内存。ramfs没有对应文件系统设备,所以它的数据永远都不会回写回去,也就不会标识为clean,因此系统也永远不会释放ramfs所占用的内存。 因为ramfs直接使用了内核已有的磁盘高速缓存机制,所以它的实现代码非常小。也由于这个原因,ramfs特性不能通过内核配置参数删除,它是内核的天然特性。 五、ramfs不是ramdisk ramdisk是在一块内存区域中创建的块设备,用于存放文件
8、系统。ramdisk的容量是固定的,不能象ramfs一样动态增长。ramdisk需要内核的文件系统驱动程序(如ext2)来操作其上的数据,而ramfs则是内核的天然特性,无需额外的驱动程序。ramdisk也象其他文件系统设备一样,需要在块设备和内存中的磁盘高速缓存之间复制数据,而这种数据复制实际不必要的。 六、从ramfs派生的文件系统tmpfs ramfs的一个缺点是它可能不停的动态增长直到耗尽系统的全部内存,所以只有root或授权用户允许使用ramfs。为了解决这个问题,从ramfs派生出了tmpfs文件系统,增加了容量大小的限制,而且允许把数据写入交换分区。由于增加了这两个特性,所以tm
9、pfs允许普通用户使用。 关于tmpfs文件系统更多的信息,可以看内核源码中的 Documentation/filesystems/tmpfs.txt 文档。 综上所述,initramfs是一种ramfs文件系统,在内核启动完成后把它复制到rootfs中,作为内核初始的根文件系统,它的任务是挂载系统真正的根文件系统。这就是initramfs的前世今生。精通initramfs构建step by step (三):busybox 七、什么是busybox busybox号称是嵌入式Linux中的瑞士军刀小巧、功能齐全。它把许多常用的Linux命令都集成到一个单一的可执行程序中,只用这一个可执行程序
10、(即busybox)加上Linux内核就可以构建一个基本的Linux系统。busybox程序非常小巧,包含全部命令可执行文件大小也只有750多K。busybox是完全模块化的,可以很容易地在编译时增加、删除其中包含的命令。 由于busybox的这些特点,它广泛应用于LiveCD、应急修复盘、安装盘等系统中。我们也是以它为基础,构建initramfs。 八、busybox的配置、编译和安装 (1)去 去下载最新的源码,解压展开。 (2)用 make menuconfig 命令启动配置界面配置,配置busybox的特性、选择要包含在busybox的命令(busybox称为applet); 也可以用
11、 make defconfig 命令做缺省配置,包含全部的applet。 另外两个配置命令是 make allyesconfig最大配置 make allnoconfig最小配置 它们和make defconfig命令都可以用来作为自定义配置的初始配置,然后再用make menuconfing命令做定制化配置。 为了简单,我们用make defconfig做缺省配置。 (3)用 make 命令编译busybox软件。 (4)用 make CONFIG_PREFIX=<安装目录> install 九、在image下创建必要的目录和设备文件 (1)在imgae目录下创建 proc ,
12、sys , etc ,mnt 四个目录 (2)hello world 已经创建了console 设备文件,我们再用 mknod -m 600 dev/null c 1 3 命令创建另一个基本的设备文件。 十、试验一下 busybox的构建和准备工作做完了,我们试验一下吧: 在image目录下以root用户权限 (1)用 mount -vt proc proc =proc mount -vt sysfs sysfs =sys 命令安装内核虚拟文件系统 (2)用 mount -v -o bind /dev dev 命令绑定/dev的设备文件到image/dev (3)用 chroot . /bin
13、/sh 命令进入busybox的环境。出现shell的命令提示符,可以试着输入几个命令,看看执行结果。例如,输入 fdisk -l 命令看看是否能显示硬盘的分区。(四):mini linux 十一、自动生成/dev下的设备文件 上节用chroot方法试验busybox时,为了简单,是用“绑定”的方式把主机的/dev中的设备文件映射到image目录下的dev目录。在initramfs上,这种方法显然不能使用。 生成系统的设备文件,现在通常都是用udev动态生成,而initramfs为了做到通用,动态生成的要求是必须的。在busybox中有一个mdev命令,就是用来动态生成设备文件,填充到/dev
14、目录的。 在系统启动时,用 mdev -s 命令可以根据内核的sysfs文件系统在/dev目录中自动生成相应的设备文件。命令执行前,需要先挂载内核的proc和sysfs虚拟文件系统。 十二、初始身手 解决了自动生成设备文件的问题后,我们可以试着做一个最简单的可运行的linux系统了: (1)在image目录下写一个最简单的init脚本。 #!/bin/sh mount -t proc proc /proc mount -t sysfs sysfs /sys mdev -s /bin/sh (2)为init脚本设置可执行权限,否则内核不会去执行它。 chmod +x init (3)有些busy
15、box配置中,mdev命令需要读取/etc/mdev.conf文件,为了避免出错信息,我们创建一个空文件。 touch etc/mdev.conf (4)在内核源码目录下,执行 make 命令,重新编译内核,生成新的initramfs。 好了,在QEMU模拟环境下启动这个新的内核,系统初始化后,会进入SHELL环境。在这个SHELL环境下,试验一些常用命令,看看是否可以正常运行。 十三、can't access tty 上一步创建的简单linux系统在进入SHELL环境时,会打出下面这一句出错信息: /bin/sh: can't access tty; job controll
16、 off 虽然不影响使用,但终究不够完美。产生这个错误的原因是我们的SHELL是直接运行在内核的console上的,而console是不能提供控制终端(terminal)功能的,所以必须把SHELL运行在tty设备上,才能消除这个错误。解决问题的办法是使用正规init机制,在执行SHELL前打开tty设备。 另外,这个简单系统的reboot、halt等命令是不起作用的,也必须通过init方式解决。 十四、busybox的缺省init模式 busybox支持init功能,当系统没有/etc/inittab文件时,它有一套缺省的模式,按下面配置执行: :sysinit:/etc/init.d/rc
17、S :askfirst:/bin/sh :ctrlaltdel:/sbin/reboot :shutdown:/sbin/swapoff -a :shutdown:/bin/umount -a -r :restart:/sbin/init 如果busybox检测到/dev/console不是串口控制台,init还要执行下面的动作: tty2:askfirst:/bin/sh tty3:askfirst:/bin/sh tty4:askfirst:/bin/sh 我们试试这种模式是否可以解决我们的问题。 (1)写/etc/init.d/rcS脚本 这个脚本实际是要执行系统的初始化操作。我们把前面
18、的init脚本改造一下,将最后的/bin/sh命令删除,然后移到 etc/init.d目录下,改名为rcS。 (2)initramfs不需要linuxrc,而且如果没有init文件,内核就不认为它是一个有效的initramfs,因而不安装它,导致内核panic。于是,我们在image目录下,把busybox安装的linuxrc改名为init mv linuxrc init (3)重新编译内核,生成新的initramfs (4)用QEMU试验一下新编译的内核。系统启动后,会打出一句话“please press Enter to active this console”感觉还不错。但是按下回车键后
19、,系统依然会打出错误信息“-/bin/sh: can't access tty; job controll off ”。用tty命令看看当前的终端设备文件名: # tty /dev/console 它还是console,不是tty设备,所以问题没有解决。不过,reboot和halt命令倒是可以正常工作了。 经过验证,busybox的缺省init模式无法满足我们的要求,我们还是要写inittab,定制自己的init初始化流程。 十五、busybox的inittab文件格式说明 要写自己的inittab,需要理解busybox的inittab文件格式。 busybox的inittab文件与
20、通常的inittab不同,它没有runlevel的概念,语句功能上也有限制。inittab语句的标准格式是 <id>:<runlevels>:<action>:<process> 各字段的含义如下 <id>: id字段与通常的inittab中的含义不同,它代表的是这个语句中process执行所在的tty设备,内容就是/dev目录中tty设备的文件名。由于是运行process的tty设备的文件名,所以也不能象通常的inittab那样要求每条语句id的值唯一。 <runlevels>: busybox不支持runlevel,所
21、以此字段完全被忽略。 <action>: 为下列这些值之一: sysinit, respawn, askfirst, wait,once, restart, ctrlaltdel, shutdown 其含义与通常的inittab的定义相同。特别提一下askfirst,它的含义与respawn相同,只是在运行process前,会打出一句话“please press Enter to active this console”,然后等用户在终端上敲入回车键后才运行process。 <process>: 指定要运行的process的命令行。 十六、写mini linux的ini
22、ttab 理解了busybox的inittab格式,我们就可以写mini linux的inittab: :sysinit:/etc/init.d/rcS tty1:askfirst:/bin/sh tty2:askfirst:/bin/sh tty3:askfirst:/bin/sh tty4:askfirst:/bin/sh tty5:askfirst:/bin/sh tty6:askfirst:/bin/sh :restart:/sbin/init :ctrlaltdel:/sbin/reboot :shutdown:/bin/umount -a -r 把这个文件放到image的etc目录
23、下。为了执行reboot命令时避免提示找不到/etc/fstab文件,我们再在etc目录下创建一个空文件 touch fstab 做好了这些,就可以重新编译内核,生成新的initramfs了。在QEMU试验环境下验证新生成的mini linux,系统运行正常,而且象通常的linux系统一样,用ALTF1F6键可以在6个终端间切换。(五)initrd 十七、配置内核支持initrd十八、用cpio命令生成initramfs cpio命令有三种操作模式:copyout、copyin、copypass,生成initramfs用的是它的copyout模式,即把文件打包的操作模式。cpio的copyou
24、t操作模式使用 -o 命令行选项指定。缺省情况下,cpio从标准输入读取输入数据,向标准输出写入输出数据。使用 -I 选项可以指定文件名代替标准输入,使用 -O 选项可以指定文件名代替标准输出,而 -F 选项指定的文件名则根据cpio操作模式的不同可代替标准输入或标准输出。 把/initramfs-test/image目录下的文件打包成initramfs,执行下面的命令: 十九、cpio命令的其他用法mkdir /initramfs-test/initramfs_data cd /initramfs-test/initramfs_data 在标准输出中打出文件名列表。 使用 -v 选项可以在c
25、pio命令执行时输出详细信息:在打包或展开文件时,输出已处理的文件名;与 -t 选项连用时,则显示文件的详细信息,类似 ls -l 的输出内容。-V 选项则用打点的方式,显示cpio命令的执行进度信息,一个点代表处理一个文件。(六)switch_root 二十、switch_root 命令 除了基于initramfs的系统(如第四节的mini linux),通常initramfs都是为安装最终的根文件系统做准备工作,它的最后一步需要安装最终的根文件系统,然后切换到新根文件系统上去。以往的基于ramdisk 的initrd 使用pivot_root命令切换到新的根文件系统,然后卸载ramdisk
26、。但是initramfs是rootfs,而rootfs既不能pivot_root,也不能umount。为了从initramfs中切换到新根文件系统,需要作如下处理: (1)删除rootfs的全部内容,释放空间 find -xdev / -exec rm '' '' (2)安装新的根文件系统,并切换 cd /newmount; mount -move . /; chroot . (3)把stdin/stdout/stderr 附加到新的/dev/console,然后执行新文件系统的init程序 上述步骤比较麻烦,而且要解决一个重要的问题:第一步删除rootfs的所
27、有内容也删除了所有的命令,那么后续如何再使用这些命令完成其他步骤?busybox的解决方案是,提供了switch_root命令,完成全部的处理过程,使用起来非常方便。 switch_root命令的格式是: switch_root -c /dev/console NEW_ROOT NEW_INIT ARGUMENTS_TO_INIT 其中NEW_ROOT是实际的根文件系统的挂载目录,执行switch_root命令前需要挂载到系统中;NEW_INIT是实际根文件系统的init程序的路径,一般是/sbin/init;-c /dev/console是可选参数,用于重定向实际的根文件系统的设备文件,一般
28、情况我们不会使用;而ARGUMENTS_TO_INIT则是传递给实际的根文件系统的init程序的参数,也是可选的。 需要特别注意的是:switch_root命令必须由PID=1的进程调用,也就是必须由initramfs的init程序直接调用,不能由init派生的其他进程调用,否则会出错,提示: switch_root: not rootfs 也是同样的原因,init脚本调用switch_root命令必须用exec命令调用,否则也会出错,提示: switch_root: not rootfs 二十一、实践:用initramfs安装CLFS根文件系统 现在实践一下switch_root命令,用它切
29、换一个CLFS的根文件系统硬盘分区。我的CLFS安装在/dev/sda8硬盘分区,我们就以此为例说明。 我们还是在以前的image目录中构建 (1)改写init脚本 #!/bin/sh mount -t proc proc /proc mount -t sysfs sysfs /sys mdev -s mount /dev/sda8 /mnt (注意:为了简单,我们直接把CLFS分区写死在init脚本中了) exec switch_root /mnt /sbin/init (2)生成新的initrd 按上一节“精通initramfs构建step by step (五):initrd”描述的cp
30、io命令生成新的initrd。 (3)把新的initrd拷贝到CLFS分区的/boot目录下,改名为clfs-initrd (4)在GRUB的menu.lst配置文件中增加一个启动项 #test for initramfs of CLFS title test for initramfs of CLFS (on /dev/sda8) root (hd0,7) kernel /boot/clfskernel-.13 (注意:并没有向内核传递root参数信息) initrd /boot/clfs-initrd 全部做完后,重启机器,选择 test for initramfs of CLFS 启动项
31、,机器顺利进入了CLFS系统,我们构建的initramfs用switch_root命令完成了CLFS实际根文件系统的安装和切换。(七)modules 二十二、内核模块支持 到目前为止,我们在构建initramfs时还没有涉及内核模块的支持,所用到的硬件驱动程序都是直接编译到内核中。现在我们就看看如何使initramfs支持内核模块。 首先,内核配置要支持模块,并支持内核模块的自动加载功能:在内核配置菜单中的激活下面的配置项,编译进内核 Load module support / Enable loadable module support / Automatic kernel loading
32、; 然后把需要的硬件驱动程序配置模块形式,比如把我的机器上的硬盘控制器的驱动编译成模块,则选择 Device Driver |->SCSI device support |->SCSI disk support |->verbose SCSI error reporting (不是必须的,但可方便问题定位) |->SCSI low-level drivers |->Serial ATA (SATA) support |->intel PIIX/ICH SATA support 把它们配置成模块。 最后,编译内核,并把编译好的内核模块安装到image的目录下:
33、 make make INSTALL_MOD_PATH=/initramfs-test/image modules_install 命令执行完毕后,在image/lib/modules/.13/kernel/drivers/scsi目录下安装了4个内核模文件:scsi_mod.ko、sd_mod.ko、ata_piix.ko、libata.ko,它们就是所需的硬盘控制器的驱动程序。 好了,都准备好了,可以用cpio命令生成inintramfs了。不过,为了方便后面的试验,我们再把init脚本改成 #!/bin/sh mount -t proc proc /proc mount -t sysfs
34、 sysfs /sys mdev -s exec /bin/sh 使系统启动后进入shell环境,并且用exec调用的方式,使shell的pid为1,能够执行switch_root命令。 二十三、试验:用initramfs中的内核模块安装硬盘文件系统insmod scsi_mod insmod libata insmod ata_piix insmod sd_mod 然后再用 mdev -s 命令生成硬盘的设备文件。 好了,可以安装CLFS的硬盘分区,并把根文件系统切换到CLFS的硬盘分区: mount /dev/sda8 /mnt exec switch_root /mnt /sbin/in
35、it 系统正常启动到了CLFS,我们可以做到用initramfs中的硬盘控制器的驱动模块安装硬盘分区了。 二十四、mdev的hotplug模式 上面的试验中,我们在加载完驱动模块后调用了mdev -s 命令来生成硬盘的设备文件。其实,可以使用mdev的hotplug模式在加载内核时自动生成对应的设备文件: 在执行insmod命令前,用 echo /sbin/mdev > /proc/sys/kernel/hotplug 命令设置系统的hotplug程序为mdev。 后续使用insmod命令加载模块时,系统自动调用mdev生成相应的设备文件。 注意:内核必须配置支持hotplug功能,而前
36、面提到的CLFS最简内核配置方案是没有配置hotplug支持的。(八)coldplug 二十五、udev的coldplug模式 内核在启动时已经检测到了系统的硬件设备,并把硬件设备信息通过sysfs内核虚拟文件系统导出。udev扫描sysfs文件系统,根据硬件设备信息生成热插拔(hotplug)事件,udev再读取这些事件,生成对应的硬件设备文件。由于没有实际的硬件插拔动作,所以这一过程被称为coldplug。我们的initramfs就是利用这一机制,加载硬件设备的驱动程序模块。 udev完成coldplug操作,需要下面三个程序: udevd作为deamon,记录hotplug事件,然后排队
37、后再发送给udev,避免事件冲突(race conditions)。 udevtrigger扫描sysfs文件系统,生成相应的硬件设备hotplug事件。 udevsettle查看udev事件队列,等队列内事件全部处理完毕才退出。 在initramfs的init脚本中可以执行下面的语句实现coldplug功能: mkdir -p /dev/.udev/db udevd -daemon mkdir -p /dev/.udev/queue udevtrigger udevsettle 许多文档提到的在udevd -daemon 命令前要执行 echo > /proc/sys/kernel/h
38、otplug 命令,经验证,在我们的initramfs环境下的coldplug功能中并不需要。 二十六、试验:用udev自动加载设备驱动模块 了解了udev的coldplug的机理,我们就试验一下用udev自动加载设备驱动模块,并生成硬件设备文件。 (1)从 /sbin 目录下拷贝udevd、udevtrigger、udevsettle程序到image目录下的sbin目录下,并用ldd命令找到它们所需要的动态库文件,拷贝到image目录下的lib目录下。 (2)修改init脚本,增加coldplug功能: #!/bin/sh mount -t proc proc /proc mount -t
39、sysfs sysfs /sys mdev -s #using udev autoload hard disk driver module mkdir -p /dev/.udev/db udevd -daemon mkdir -p /dev/.udev/queue udevtrigger udevsettle mount /dev/sda8 /mnt killall udevd exec switch_root /mnt /sbin/init 注意:在切换到真正根文件系统前,要把udevd进程杀掉,否则会和真正根文件系统中的udev脚本的执行相冲突。这就是上面killall udevd 语句的
40、作用。 (3)编写udev规则文件 规则文件是udev的灵魂,没有规则文件,udev无法自动加载硬件设备的驱动模块。为了简单,我们直接使用CLFS中的40-modprobe.rules,把它拷贝到image目录下的etc/udev/rules.d目录。有关udev的规则文件编写,已超出了本文的范围,后续我有可能专文描述。 # # # Description : 40-modprobe.rules # # Authors : Based on Open Suse Udev Rules # # # Adapted to : Jim Gifford # LFS : Alexander E. Patr
41、akov # # Version : 00.01 # # Notes : # # # hotplug ENVMODALIAS="?*", RUN+="/sbin/modprobe $envMODALIAS" # scsi SUBSYSTEM="scsi_device", ACTION="add", SYSFSdevice/type="0|7|14", RUN+="/sbin/modprobe sd_mod" SUBSYSTEM="scsi_device",
42、 ACTION="add", SYSFSdevice/type="1", SYSFSdevice/vendor="OnsStream", RUN+="/sbin/modprobe osst" SUBSYSTEM="scsi_device", ACTION="add", SYSFSdevice/type="1", RUN+="/sbin/modprobe st" SUBSYSTEM="scsi_device", ACT
43、ION="add", SYSFSdevice/type="45", RUN+="/sbin/modprobe sr_mod" SUBSYSTEM="scsi_device", ACTION="add", RUN+="/sbin/modprobe sg" # floppy KERNEL="nvram", ACTION="add", RUN+="load_floppy_module.sh" 注意:上面的 ENVMODAL
44、IAS="?*", RUN+="/sbin/modprobe $envMODALIAS" 语句是实现自动加载硬件设备驱动模块功能的关键,它根据sysfs文件系统中记录的模块aliases数据,用modprobe命令加载对应的内核模块。有关模块aliases的进一步说明,可参考CLFS手册(CLFS-(九)内核编译时构建initramfs补遗 二十七、直接把cpio打包文件编译进内核 如果我们有一个已经做好的cpio格式的initramfs,可以在内核编译时直接编译进内核。回忆一下第一节的内容,我们在内核配置参数中的initramfs sources配置项
45、下输入构建initramfs的目录路径。其实我们也可以直接输出现成的initramfs的文件名,这样在内核编译时,就可以把它编译进内核了。 使用这种方法,有两点需要注意: (1)cpio文件不能压缩。一般作为initrd的cpio文件都经过了压缩,所以编译前需要先把压缩过的文件解压。 (2)cpio文件的后缀名必须是 .cpio。内核编译通过 .cpio的后缀名来识别此文件是cpio打包文件,而其他文件后缀名则会被认为是initramfs构建的描述文件(关于描述文件,下面后详细说明)。 二十八、用描述文件构建initramfs 用内核编译工具构建initramfs的第三种方法是使用描述文件。在
46、内核配置参数中的initramfs sources配置项下可以输入initramfs构建描述文件的文件名,内核编译工具根据描述文件完成initramfs的构建。 描述文件的语法格式的说明如下: # a comment file <name> <location> <mode> <uid> <gid> dir <name> <mode> <uid> <gid> nod <name> <mode> <uid> <gid> <dev_typ
47、e> <maj> <min> slink <name> <target> <mode> <uid> <gid> pipe <name> <mode> <uid> <gid> sock <name> <mode> <uid> <gid> <name> name of the file/dir/nod/etc in the archive <location> location of the
48、 file in the current filesystem <target> link target <mode> mode/permissions of the file <uid> user id (0=root) <gid> group id (0=root) <dev_type> device type (b=block, c=character) <maj> major number of nod <min> minor number of nod 例子: 我们用描述文件的方式,构建第一节中的he
49、llo world的initramfs。 hello-init.desp: dir /dev 0755 0 0 nod /dev/console 0600 0 0 c 5 1 file /init /home/wyk/initramfs-test/hello_static 0755 0 0 在内核配置项initramfs sources中指定描述文件hello-init.desp,编译内核时就会生成hello world的initramfs,运行效果与第一节用指定构建目录的方法构建的initramfs的完全相同。 注意:在内核帮助文件中,提到initramfs sources配置项可以指定多个
50、目录或描述文件,内核会汇集这些目录或文件生成一个initramfs。但从我的试验来看,initramfs sources只接受单一的目录名或文件名,输出多个目录名或文件名(之间用空格分隔),内核编译时就会出错。也许是我的方法有误,还望读者指正。(十)uclibc 二十九、toolchain 在initramfs中使用uclibc库,关键是构建uclibc的工具链toolchain。构建uclibc 的 toolchain 有两种主要方式:(1)用buildroot工具( )自动构建,这也是uclibc的官方标准做法。(2)用CLFS Embedded手册的方法手工创建。目前CLFS Embed
51、ded还在开发中,可在/view/clfs-embedded/x86/中查阅。 我们简单地说明用buildroot工具构建uclbic的toolchain的步骤: (1)获取buildroot。 推荐用svn命令从它的版本库中下载: svn co svn://trunk/buildroot 要求使用svn命令,需要先安装subversion软件包。下载过程中,可能会出现连接异常中断的情况,这时重新执行上述命令,继续进行下载,有可能要重复多次。 (2)配置buildroot 因为我们只是创建toolchain,所以需要做相应的配置。在bu
52、ildroot的顶层目录下,执行 make menuconfig 命令,在缺省配置的基础上做如下配置 Target Architecture: i386 Target Architecture Variant: i686 Package Selection for the target: 取消BusyBox的选项(缺省是选中的) Target filesystem options: 取消 ext2 root filesystem(缺省是选中的) Toolchain -> Toolchain type: Buildroot toolchain (3)编译 执行 make 命令,buildr
53、oot工具会自动下载所需要的源文件并自动编译,等一两个小时后,toolchain就编译好了。编译好的toolchain位于 buildroot/build_i686/staging_dir/usr/bin/ 目录下。工具命令的前缀是 i686-linux- 。 三十、编译Busybox静态连接uclibc库 一般而言,使用uclibc库是为了把它静态连接到busybox中。具体步骤是: (1)把uclibc toolchain的目录添加到PATH中。 在/.bash_profile文件中添加: #set PATH so it includes uclibc toolchain if it ex
54、ist if -d /buildroot/build_i686/staging_dir/usr/bin ; then PATH="$PATH":/buildroot/build_i686/staging_dir/usr/bin fi (2)配置busybox静态连接库。 在busybox的配置界面中,选择: Build Options -> Build BusyBox as a static binary (no shared libs) (3)编译 执行 make CROSS_COMPILE=i686-linux- 命令“交叉编译”busybox。 最后编译生成的是
55、静态连接的可执行文件,不需要在initramfs中拷贝库文件。 三十一、用buildroot自动构建initramfs buildroot工具实际是一个功能强大的根文件系统构建工具,它以uclibc和busybox作为系统构建的基础,toolchain只是它构建系统的中间产品。initramfs是一种特殊的根文件系统,当然也可以用buildroot工具自动构建,下面是构建方法的简要描述: (1)配置 在buildroot的配置界面下做如下的配置: Package Selection for the target: 选择 Busybox Run Busybox's own full in
56、stallation Use minimal target skeleton Target filesystem options -> cpio the root filesystem -> comprassion method: gzip (2)编译 执行 make can't open /dev/tty1: No such file or directory can't open /dev/tty2: No such file or directory can't open /dev/tty3: No such file or directory 错误信
57、息的循环输出,系统不能正常运行。 错误的原因是没有在initramfs的/dev目录下生成相应的设备文件。需要做如下的调整: 1)在构建目录(buildroot/project_build_i686/uclibc/root)下的etc/init.d目录中新增一个初始化脚本文件S10mountfs #!/bin/sh mount -t proc proc /proc mount -t sysfs sysfs /sys mdev -s 2)更改busybox的setuid属性,否则无法执行mount命令。在构建目录(buildroot/project_build_i686/uclibc/root)下执行 chmod -s bin/busybox (十一)klibc 三十二、编译klibc (1)在下载klibc的源码,目前最新版本是1.5。 (2)解开源码,并在顶层目录建立一个符号链接linux,指向linux的内核源码。注意,内核源码必须已通过make menuconfig等命令配置好。 (3)执行 make 命令,编
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 陇南地区武都县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 凉山彝族自治州冕宁县2025-2026学年第二学期四年级语文第六单元测试卷(部编版含答案)
- 洛阳市洛宁县2025-2026学年第二学期四年级语文期中考试卷(部编版含答案)
- 邢台市平乡县2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 枣庄市薛城区2025-2026学年第二学期六年级语文第五单元测试卷部编版含答案
- 公司年中会议策划方案
- 深度解析(2026)《CBT 4430.2-2019船舶螺旋桨用铸造铝铍钴青铜化学分析方法 第2部分:铍量的测定铬天青S光度法和重量法》
- 深度解析(2026)《AQT 2010-2006金属非金属矿山安全生产管理人员安全生产培训大纲》
- 2026-2027年人工智能(AI)在职业高尔夫球手训练中通过挥杆数据分析提供个性化技术调整建议获高端体育科技投资
- 5 草船借箭 表格式公开课一等奖创新教案
- cnc编程面试题及答案
- T/CCAS 010-2019水泥窑协同处置飞灰预处理产品水洗氯化物
- 大学物理力学5功和能
- T-CPI 11037-2024 石油天然气钻采设备水力振荡器技术与应用规范
- 人教版PEP四年级英语下册全册单元测试卷(附听力材料)
- 尼康CoolPixP100中文说明书
- 大学生春季传染病预防知识
- 《Python程序设计任务驱动教程》 课件-第2章 Python基础
- 工程项目送检验收方案
- 国家职业技术技能标准 4-04-05-05 人工智能训练师 人社厅发202181号
- 【八年级上册地理】一课一练2.2 世界的气候类型 同步练习
评论
0/150
提交评论