没有合适的资源?快使用搜索试试~ 我知道了~
linux内核入门Chapter9.pdf
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 153 浏览量
2021-11-04
20:55:52
上传
评论
收藏 107KB PDF 举报
温馨提示
试读
24页
linux内核入门Chapter9.pdf
资源推荐
资源详情
资源评论
第 9 章 编译 Linux 内核
本章包括:
9.1 工具链
9.2 编译内核源代码
小结
习题
到此为止 , 我们已经认识了 linux 内核子系统,也探究了系统的初始化函数。同样,了
解内核映像的创建也是非常重要的。 本章将讨论内核映像的编译和链接过程, 并考察内核的
编译过程。
9.1 工具链( toolchain )
工具链( toolchain )是创建 linux 内核映像的一组程序集合。链的概念源于一工具的
输出将作为另一工具的输入这一特点。 工具链包含编译程序、 汇编程序和链接程序。 从技术
上讲,还需一个文本编辑器。本节只讨论前三个工具。开发软件时工具链必不可少,当然,
软件开发工具包( SDK)也是必需的。
编译程序( compiler )是一个转换程序, 可将高级源语言转换成低级目标语言( object
language )。目标代码是运行在目标系统上并依赖于机器的一系列指令。汇编程序
(assembler )也是一个转换程序,可将汇编语言转换成与编译程序相同的目标代码。其不
同之处在于: 汇编程序产生的机器指令与汇编语句一一对应, 而高级语言的每条语句可能对
应多条机器指令。如你所知, linux 源代码中与体系结构相关的某些文件是用汇编语言编写
的,它们调用汇编程序将其编译为目标代码。
链接编辑程序( link editor )或链接程序( linker )可将多个可执行模块链接成一个
单元,以便执行。
图 9.1 说明了工具链的链式关系。 链接程序将把程序的目标代码与它使用的所有函数库
链接起来。编译程序中含有标志位,可供用户选择编译级别。例如:图 9.1 中可以看到,编
译程序可以直接产生机器代码, 也可以先编译成汇编语言, 再经由汇编程序把它组合成计算
机可直接执行的机器指令。
9.1.1 编译程序
通常, 编译程序也具有链式特性,它分成多步执行,一步的输出作为下一步的输入,图
9.2 是其图解。编译的第一步是词法扫描( scanner ),它将高级语言编写的程序拆分为一
一个个的单词符号( tokens )。接下来,语法分析( parser )阶段根据一定的语法规则将这
些符号组织起来, 并由上下文分析阶段根据语义属性进一步组织这些符号。 优化程序可提高
所解析的符号的效率, 代码生成阶段则产生目标代码。 编译程序输出符号表和可重定位的目
标代码。换句话说,每一个已编译的模块其起始地址都是 0,链接时必须重定位到合适的位
置。
图 9.2 编译程序的操作过程
9.1.2 交叉编译
工具包通常自然地 (natively )运行, 这就意味着编译代码的系统和运行目标代码的系
统相同。 如果在 x86 系统上开发了一个内核, 把它装载到另一个 (或同样的) x86 系统上时,
无须进行任何编译工作。 功能强大的 Macs 和数量繁多的 x86 工具包可将代码编译成能在相
应体系结构上运行的代码。 但是, 如果我们想在一种平台下编写代码, 而在另一种平台下运
行呢?
听来容易做来难! 考虑一下嵌入式市场, 嵌入式系统通常是在有限内存和 I/O 接口的环
境中实现其功能。 无论控制的是汽车, 路由器还是手机, 这些设备都不足以容纳一个完整的
嵌入式系统开发环境 (更不用说监视器和键盘)。 解决的办法就是,让开发者利用他们功能
强大、相对廉价的工作站作为宿主机( host systems )来开发代码,然后将这些代码下载到
目标系统( target system )上进行检测。因而称之为交叉编译!
例如: 你可能是 PowerPC嵌入式系统的开发者, 该系统使用 405 处理器。 而你的台式机
绝大多数都是 x86 的。通过使用 gcc,你可以在这些台式机上完成所有开发工作(包括 C程
序和汇编程序),只要在编译时使用 -mcpu=405 选项
1
就可以了。这样产生的目标代码具有
405 处理器特有的指令和寻址方式。之后就可以把目标代码下载到嵌入式系统中运行并调
试。这样做看起来确实很乏味,但是对资源有限的嵌入式系统而言,它大大节省了内存。
在这种特殊环境下,许多用于交叉编译的辅助开发调试工具也应运而生。
9.1.3 链接程序
编译一个 C程序时(例如,“ Hello world ”),生成的代码远不止 .c 文件中的这三四
行。链接程序的工作就是找出所有引用的外部模块并链接起来。 这些外部模块或函数库一般
来自于开发者、操作系统和C运行库( printf ()的出处)。链接程序取出这些函数库,修
订指针位置(重定位),并交叉引用模块中的解析符号,最终产生一个可执行模块。符号可
以是全局的也可以是局部的。 全局符号可以在模块内部定义, 或由另一模块外部引用。 链接
程序要找到与模块相关的所有符号的定义。 (注意:内核开发者无法使用用户函数库。)对
于普通函数, 内核自身有对应的函数。 静态库是在链接时被找到并拷贝的, 而动态库和共享
库是在运行时才装载的,并让所有的进程共享。 Microsoft 和 OS/2 将共享库称为动态链接
库。 Linux 提供的系统调用 dlopen( ) , dlsym( ) 及 dlclose( ) 用于加载 / 打开共享库,查
找库中的符号以及关闭共享库。
9.1.4 ELF 二进制目标文件
目标文件的格式随着生产商的不同而不同。现今,大多数 UNIX系统都使用可执行链接
格式( ELF二进制格式)。 ELF文件有多种不同类型并执行不同的函数。主要的 ELF 文件类
型有可执行文件( executable files )、可重定位目标文件( relocatable object files )、
核心文件( core file )及共享库( shared librarie )。 ELF格式支持目标文件对不同平台
和体系结构兼容。图 9.3 阐明可执行 ELF文件和非可执行 ELF文件。
图 9.3 可执行 ELF文件和非可执行 ELF文件
1
了解更多应用于 IBM RS/6000 (POWER) 及 PowerPC 的g cc 选项,可登录:
http://gcc.gnu.org/onlinedocs/gcc/RS_002f6000-and-PowerPC-Options.html#RS_002f6000-and-PowerPC-Options
ELF 文件头总是位于 ELF文件中偏移为 0 的位置, ELF文件的所有信息均可通过 ELF文
件头获得。 ELF文件头是目标文件中唯一固定的结构,因而它必须能够定位并说明文件中其
它子结构的位置和大小。所有 ELF文件都被分为许多具有相似数据块的节( section )或段
(segment) 。非可执行目标文件包含多个节( sections )和一个节头表( section header
table ),可执行目标文件则包含多个段 (segments)和一个程序头表 (program header table )。
9.1.4.1 ELF 文件头
在 linux 系统中,数据结构 elf32_hdr 存储 ELF文件头( 32 位的系统使用该结构, 64
位的系统则使用 elf64_hdr 结构)。我们来看看这个结构:
-----------------------------------------------------------------------
include/linux/elf.h
234 #define EI_NIDENT 16
235
236 typedef struct elf32_hdr{
237 unsigned char e_ident[EI_NIDENT];
238 Elf32_Half e_type;
239 Elf32_Half e_machine;
240 Elf32_Word e_version;
241 Elf32_Addr e_entry; /* Entry point */
242 Elf32_Off e_phoff;
243 Elf32_Off e_shoff;
244 Elf32_Word e_flags;
245 Elf32_Half e_ehsize;
246 Elf32_Half e_phentsize;
247 Elf32_Half e_phnum;
248 Elf32_Half e_shentsize;
249 Elf32_Half e_shnum;
250 Elf32_Half e_shstrndx;
251 } Elf32_Ehdr;
-----------------------------------------------------------------------
237 行:
e_ident 域存放了一个 16 字节的魔数,用于标识该文件是否为 ELF文件。
238 行:
e_type 域指定目标文件类型,例如:可执行文件,重定位文件,共享文件等。
239 行:
e_machine 域表示被编译文件所在系统的体系结构。
240 行:
e_version 域表示目标文件的版本。
241 行:
e_entry 域保存程序的起始地址。
242 行:
e_phoff 域保存程序头表在文件中的偏移量 ( 按字节计数 ) 。
243 行:
e_shoff 域保存节头表在文件中的偏移量 ( 按字节计数 ) 。
244 行:
e_flags 域保存特定处理器标志。
245 行:
e_ehsize 域保存 ELF 头的大小。
剩余23页未读,继续阅读
资源评论
霖落^0^时空
- 粉丝: 3
- 资源: 9万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功