曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5960|回复: 0
打印 上一主题 下一主题

几个重要的 linux 内核文件

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2009-8-1 11:17:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在 /boot 目录下有诸如这样几个文件:
vmlinuz-2.6.29.3
System.map-2.6.29.3
initrd-2.6.29.3.img

1、vmlinuz-2.6.29.3
vmlinuz 是可引导的、经过压缩的,可执行的内核。"vm" 是 "Virtual Memory" 之意。Linux 支持虚拟内存,能用硬盘空间作为虚拟内存,所以 "vm" 因此得名。vmlinuz 后面的 2.6.29.3 代表的是内核版本号。

建立 vmlinuz 有两种方式:
make zImage

make bzImage

zImage 适用于小内核,它的存在是为了向后兼容;而 bzImage 编译出来的内核则比较大,"bz" 就是表示 "big zImage"。
zImage(vmlinuz) 和 bzImage(vmlinuz) 都是用 gzip 压缩的。它们不仅是一个 压缩文件,而且在这两个文件的开头部分内嵌有 gzip 解压缩代码。所以不能用 gunzip 或 gzip -dc 解压缩 vmlinuz 。尝试解压则出现下面的错误提示:
[root@localhost ~]# gunzip vmlinuz-2.6.29.3
gunzip: vmlinuz-2.6.29.3: unknown suffix -- ignored

内核文件中包含一个微型的 gzip ,用于解压缩内核并引导它。
zImage 和 bzImage 的区别在于,老的 zImage 解压缩内核到低端内存 (第一个640K),bzImage 解压缩内核到高端内存 (1M以上)。如果内核较小,可用 zImage 或 bzImage,两种方式引导系统运行时都是相同的。大的内核采用 bzImage,而不能采用 zImage。

mlinux 是未压缩的内核,vmlinuz 是 vmlinux 的压缩文件。

2、initrd-2.6.29.3.img
initrd 是 "boot loader initialized RAM disk" 的缩写。其中 2.6.29.3 是内核版本号。
initrd 一般被用来临时的引导硬件到实际内核 vmlinuz ,使之能够接管硬件并继续对系统进行引导。比如,使用的是 SCSI 硬盘,但内核 vmlinuz 中没有这个 SCSI 的硬件驱动,那么在装入 SCSI 模块之前,内核不能加载根文件系统。然而, SCSI 模块存储在根文件系统的 /lib/modules 下,而 initrd 则可以实现加载这个模块以及安装文件系统的功能。

initrd 映像文件用 mkinitrd 命令创建,在 Redhat, CentOS, OpenSuse 下都有这个工具。

initrd 在系统引导过程中使用一个临时的根文件系统,用来支持两个阶段的引导过程。实际上,initrd 就是一个带有根文件系统的虚拟 RAM 盘,里面包含了根目录 '/' ,以及其它的目录。比如 :
bin , dev, proc, sbin, sys 等 linux 启动时必须的目录,还有在 /bin 目录下加入了一些必须的可执行命令。

PC机或服务器的 linux 内核使用这个 initrd 来挂载真正的根文件系统,然后将此 initrd 从内存中卸掉,这种情况下 initrd 就是一个过渡的东西。在现在许多简单的嵌入式 linux 中,一般不卸载这个 initrd ,而是直接将其作为根文件系统使用,在这之前就需要把所需的程序以及命令还有其它文件都安装在这个文件系统中。其实现在大多数嵌入式系统也是有自己磁盘的,所以,initrd 在大多数嵌入式系统中也和一般的 linux 中的作用一样,只是起着过渡作用。

initrd 的引导过程
第二阶段引导程序,常用的是 GRUB 将内核解压缩并拷贝到内存中,然后内核接管了 CPU 开始执行,然后内核调用 init() 函数 -- 此 init() 函数并不是后来的 init 进程!然后内核调用函数 initrd_load() 在内存中加载 initrd 根文件系统。init_load() 函数又调用了其它一些函数为 RAM 磁盘分配空间,并计算 CRC 等操作。然后对 RAM 磁盘进行解压,并将其加载到内存中。现在,内存中就有了 initrd 的映像。

接着,内核会调用 mount_root() 函数来创建真正的根分区文件系统,然后调用 sys_mount() 函数来加载真正的根文件系统,接着 chdir 到这个真正的根文件系统中。

最后,init() 函数调用 run_init_process() 函数,利用 execve 来启动 init 进程,从而进入 init 的运行过程。

3、System.map-2.6.29.3
 System.map 是内核符号映射表,其意就是将内核中的符号( 也就是内核中的函数 )和它的地址能联系起来的一个列表,是所有符号及其对应地址的一个列表。之所以这样,是为了使用户编程方便 --- 直接使用函数符号就可以了,而不用去记要使用的函数地址。当编译一个新的内核时,原来的 System.map 中的符号信息就不正确了。随着每次内核的编译,就会产生一个新的 System.map 文件,并且需要用该文件取代原来的文件。

内核符号表 System.map 是由 "nm vmlinux" 产生并且虑出不相关的符号后所创建。nm 命令的作用是 “从目标文件中列出符号”。下面是符号表的一部分:
[root@localhost boot]# cat System.map-2.6.29.3 |more
00000000 A VDSO32_PRELINK
00000040 A VDSO32_vsyscall_eh_frame_size
000001d3 A kexec_control_code_size
00000400 A VDSO32_sigreturn
0000040c A VDSO32_rt_sigreturn
00000414 A VDSO32_vsyscall
00000424 A VDSO32_SYSENTER_RETURN
在 linux 中有许许多多的全局符号。Linux 内核不使用符号名,而是通过变量或函数的地址来识别变量或函数名。比如不是使用 size_t ByteRead 这样的符号,而是像 c0343f20 这样引用变量。

对于使用者,更喜欢像 size_t ByteRead 这样的名字,而不是 c0343f20 这样的名字。linux 内核主要用 C 来写,所以编译器/连接器允许我们编码时使用符号名,当内核运行时使用地址。

虽然内核本身并不真正使用 System.map ,但其它程序比如 klogd,lsof 和 ps 等软件需要一个正确的 System.map 。如果使用错误的或没有 System.map,klogd 的输出将是不可靠的,这对于派出程序故障会带来困难。没有 System.map ,可能会面临一些令人烦恼的信息。

另外,少数驱动需要 System.map 来解析符号,如果没有当前运行的特定内核所创建的 System.map ,它们就不能正常工作。

linux 的内核日志守护进程 klogd 为了执行名称-地址解析,klogd 需要使用 System.map。System.map 应当放在使用它的软件都能够找到的它的地方。执行 man kogd 知道,如果没有将 System.map 作为一个变量的位置给 klogd ,那么它将按照下面的顺序,在三个地方查找:
       /boot/System.map
       /System.map
       /usr/src/linux/System.map
System.map 也有版本信息,klogd 能够正确的查找正确的映像(map)文件
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-15 23:43 , Processed in 0.062630 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表