好文档 - 专业文书写作范文服务资料分享网站

Linux嵌入式系统环境搭建、内核配置、最小系统启动与设备文件分析

天下 分享 时间: 加入收藏 我要投稿 点赞

待调度,init())

至此start_kernel()结束,基本的核心环境已经建立起来了 3.3.2.2

外设初始化--内核引导第二部分

init()函数作为核心线程,首先锁定内核(仅对SMP机器有效),然后调用 do_basic_setup()完成外设及其驱动程序的加载和初始化。过程如下:

l 网络初始化(sock_init())

l 创建事件管理核心线程初始化(start_context_thread())

l 其他所需要的初始化都使用__initcall()宏包含,在do_initcalls()函数中启动执行。 3.3.3 最小系统启动需要关注的初始化部分

控制台初始化(console_init())

3.4 Linux2.6.11内核移植

4 第四章嵌入式设备的文件系统

4.1 ramdisk文件系统

本文以initrd 为例来介绍linux关于ramdisk的相关问题。Linux初始 RAM 磁盘(initrd)是在系统引导过程中挂载的一个临时根文件系统,initrd 与内核绑定在一起,并作为内核引导过程的一部分进行加载。用来支持两阶段的引导过程。initrd 文件中包含了各种可执行程序和驱动程序,它们可以用来挂载实际的根文件系统,然后再将这个 initrd RAM 磁盘卸载,并释放内存。在很多嵌入式 Linux 系统中,initrd 就是最终的根文件系统。 4.1.1 initrd 内容剖析及制作

Linux2.4内核的initrd的格式是文件系统镜像文件,本文将其称为image-initrd,以区别后面介绍的linux2.6内核的cpio格式的initrd。 4.1.1.1 4.1.1.1.1

Linux2.4内核的initrd 察看initrd的内容

拷贝initrd到当前目录

[root@localhost mnt]# cp /boot/initrd-2.4.18-14.img .

[root@localhost mnt]# mv initrd-2.4.18-14.img initrd-2.4.18-14.img.gz 由于initrd-2.4.18-14.img是压缩文件,要使用gunzip必须加后缀.gz [root@localhost mnt]# gunzip initrd-2.4.18-14.img.gz Mount到一个目录下 [root@localhost mnt]# ls ./mnt/

察看内容

bin dev etc lib linuxrc loopfs proc sbin sysroot

解压缩到当前文件夹

[root@localhost mnt]# mount -t ext2 -o loop initrd-2.4.18-14.img ./mnt

4.1.1.1.2

创建定制 initrd 的shell脚本

#!/bin/bash # Housekeeping... rm -f /tmp/ramdisk.img rm -f /tmp/ramdisk.img.gz

# Ramdisk Constants RDSIZE=4000 BLKSIZE=1024

# Create an empty ramdisk image

dd if=/dev/zero of=/tmp/ramdisk.img bs=$BLKSIZE count=$RDSIZE

# Make it an ext2 mountable file system

/sbin/mke2fs -F -m 0 -b $BLKSIZE /tmp/ramdisk.img $RDSIZE

# Mount it so that we can populate

mount /tmp/ramdisk.img /mnt/initrd -t ext2 -o loop=/dev/loop0

# Populate the filesystem (subdirectories)

mkdir /mnt/initrd/bin mkdir /mnt/initrd/sys mkdir /mnt/initrd/dev mkdir /mnt/initrd/proc

# Grab busybox and create the symbolic links pushd /mnt/initrd/bin

cp /usr/local/src/busybox-1.1.1/busybox . ln -s busybox ash ln -s busybox mount ln -s busybox echo ln -s busybox ls ln -s busybox cat ln -s busybox ps ln -s busybox dmesg ln -s busybox sysctl popd

# Grab the necessary dev files cp -a /dev/console /mnt/initrd/dev cp -a /dev/ramdisk /mnt/initrd/dev cp -a /dev/ram0 /mnt/initrd/dev cp -a /dev/null /mnt/initrd/dev cp -a /dev/tty1 /mnt/initrd/dev cp -a /dev/tty2 /mnt/initrd/dev

# Equate sbin with bin pushd /mnt/initrd ln -s bin sbin popd

# Create the init file

cat >> /mnt/initrd/linuxrc << EOF #!/bin/ash echo

echo \echo

mount -t proc /proc /proc mount -t sysfs none /sys /bin/ash --login EOF

chmod +x /mnt/initrd/linuxrc

# Finish up... umount /mnt/initrd gzip -9 /tmp/ramdisk.img

为了创建 initrd,我们最开始创建了一个空文件,这使用了 /dev/zero(一个由零组成的码流)作为输入,并将其写入到 ramdisk.img 文件中。所生成的文件大小是 4MB(4000 个 1K 大小的块)。然后使用 mke2fs 命令在这个空文件上创建了一个 ext2(即 second extended)文件系统。现在这个文件变成了一个 ext2 格式的文件系统,我们使用 loop 设备将这个文件挂载到 /mnt/initrd 上了。在这个挂载点上,我们现在就有了一个目录,它以 ext2 文件系统的形式呈现出来,我们可以对自己的 initrd 文件进行拼装了。接下来的脚本提供了这种功能。

下一个步骤是创建构成根文件系统所需要的子目录:/bin、/sys、/dev 和 /proc。这里只列出了所需要的目录(例如没有库),但是其中包含了很多功能。

为了可以使用根文件系统,我们使用了 BusyBox。这个工具是一个单一映像,其中包含了很多在 Linux 系统上通常可以找到的工具(例如 ash、awk、sed、insmod 等)。BusyBox 的优点是它将很多工具打包成一个文件,同时还可以共享它们的通用元素,这样可以极大地减少映像文件的大小。这对于嵌入式系统来说非常理想。将 BusyBox 映像从自己的源目录中拷贝到自己根目录下的 /bin 目录中。然后创建了很多符号链接,它们都指向 BusyBox 工具。BusyBox 会判断所调用的是哪个工具,并执行这个工具的功能。我们在这个目录中创建了几个链接来支持 init 脚本(每个命令都是一个指向 BusyBox 的链接。)

下一个步骤是创建几个特殊的设备文件。我从自己当前的 /dev 子目录中直接拷贝了这些文件,这使用了 -a 选项(归档)来保留它们的属性。

倒数第二个步骤是生成 linuxrc 文件。在内核挂载 RAM 磁盘之后,它会查找 init 文件来执行。如果没有找到 init 文件,内核就会调用 linuxrc 文件作为自己的启动脚本。我们在这个文件中实现对环境的基本设置,例如挂载 /proc 文件系统。除了 /proc 之外,我还挂载了 /sys 文件系统,并向终端打印一条消息。最后,我们调用了 ash(一个 Bourne Shell 的克隆),这样就可以与根文件系统进行交互了。linuxrc 文件然后使用 chmod 命令修改成可执行的。

最后,我们的根文件系统就完成了。我们将其卸载掉,然后使用 gzip 对其进行压缩。 4.1.1.1.3

Linux对 Initrd 的处理流程

Linux2.4内核的initrd的格式是文件系统镜像文件,linux2.4内核对initrd的处理流程如下:

1. boot loader把内核以及/dev/initrd的内容加载到内存,/dev/initrd是由boot loader初始化的设备,存储着initrd。

2. 在内核初始化过程中,内核把 /dev/initrd 设备的内容解压缩并拷贝到 /dev/ram0 设备上。

3. 内核以可读写的方式把 /dev/ram0 设备挂载为原始的根文件系统。

4. 如果 /dev/ram0 被指定为真正的根文件系统,那么内核跳至最后一步正常启动。 5. 执行 initrd 上的 /linuxrc 文件,linuxrc 通常是一个脚本文件,负责加载内核访问根文件系统必须的驱动, 以及加载根文件系统。

6. /linuxrc 执行完毕,真正的根文件系统被挂载。

7. 如果真正的根文件系统存在 /initrd 目录,那么 /dev/ram0 将从 / 移动到 /initrd。否则如果 /initrd 目录不存在, /dev/ram0 将被卸载。

8. 在真正的根文件系统上进行正常启动过程 ,执行 /sbin/init。 linux2.4 内核的

initrd 的执行是作为内核启动的一个中间阶段,也就是说 initrd 的 /linuxrc 执行以后,内核会继续执行初始化代码,这是 linux2.4 内核同 2.6 内核的 initrd 处理流程的一个显著区别。 4.1.1.2 4.1.1.2.1

Linux2.6内核的initrd 察看initrd的内容

[root@localhost temp]# gunzip initrd.img.gz

[root@localhost temp]# cpio -i --make-directories < initrd.img [root@localhost temp]# ls

bin bootsplash dev etc init lib proc root sbin sys tmp

4.1.1.2.2 创建initrd

cpio-initrd的制作非常简单,通过两个命令就可以完成整个制作过程,假设当前目录位于准备好的initrd文件系统的根目录下

[root@localhost temp]# find . | cpio -c -o > ../initrd-2.6.17.img [root@localhost temp]# gzip -9 initrd-2.6.17.img

4.1.1.2.3 Linux对 Initrd 的处理流程

linux2.6 内核支持两种格式的 initrd,一种是介绍的 linux2.4 内核那种传统格式的文件系统镜像-image-initrd,它的制作方法同 Linux2.4 内核的 initrd 一样,其核心文件就是 /linuxrc。另外一种格式的 initrd 是 cpio 格式的,这种格式的 initrd 从 linux2.5 起开始引入,使用 cpio 工具生成,其核心文件不再是 /linuxrc,而是 /init,本文将这种 initrd 称为 cpio-initrd。尽管 linux2.6 内核对 cpio-initrd和 image-initrd 这两种格式的 initrd 均支持,但对其处理流程有着显著的区别,下面分别介绍 linux2.6 内核对这两种 initrd 的处理流程。

l cpio-initrd 的处理流程

1. boot loader 把内核以及 initrd 文件加载到内存的特定位置。 2. 内核判断initrd的文件格式,如果是cpio格式。 3. 将initrd的内容释放到rootfs中。

4. 执行initrd中的/init文件,执行到这一点,内核的工作全部结束,完全交给/init文件处理。

l image-initrd的处理流程

1. boot loader把内核以及initrd文件加载到内存的特定位置。

2. 内核判断initrd的文件格式,如果不是cpio格式,将其作为image-initrd处理。 3. 内核将initrd的内容保存在rootfs下的/initrd.image文件中。

4. 内核将/initrd.image的内容读入/dev/ram0设备中,也就是读入了一个内存盘中。 5. 接着内核以可读写的方式把/dev/ram0设备挂载为原始的根文件系统。

6. .如果/dev/ram0被指定为真正的根文件系统,那么内核跳至最后一步正常启动。 7. 执行initrd上的/linuxrc文件,linuxrc通常是一个脚本文件,负责加载内核访问根文件系统必须的驱动, 以及加载根文件系统。

8. /linuxrc执行完毕,常规根文件系统被挂载。

9. 如果常规根文件系统存在/initrd目录,那么/dev/ram0将从/移动到/initrd。否则如果/initrd目录不存在, /dev/ram0将被卸载。

10. 在常规根文件系统上进行正常启动过程 ,执行/sbin/init。

通过上面的流程介绍可知,Linux2.6内核对image-initrd的处理流程同linux2.4内核相比并没有显著的变化, cpio-initrd的处理流程相比于image-initrd的处理流程却有很大的区

Linux嵌入式系统环境搭建、内核配置、最小系统启动与设备文件分析

待调度,init())至此start_kernel()结束,基本的核心环境已经建立起来了3.3.2.2外设初始化--内核引导第二部分init()函数作为核心线程,首先锁定内核(仅对SMP机器有效),然后调用do_basic_setup()完成外设及其驱动程序的加载和初始化。过程如下:l网络初始化(sock_init())
推荐度:
点击下载文档文档为doc格式
95se126yqz6tzp833x1q
领取福利

微信扫码领取福利

微信扫码分享