版权声明:本文参考了《Linux 内核设计与艺术》。 未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!
1 编译内核与内核补丁
- 获取内核源码:内核是开源的, 可以从http://www.kernel.org下载或者用git从git.kernel.org克隆。
内核源码路径:内核源码一般安装在
/usr/src/linux
目录下。但不要用于开发,也不要用root身份修改,而应当建立自己的主目录,仅以root身份安装配置内核
- 每个选项要么是二选一yes或no,要么是三选一yes、no、module。yes表示把代码编译进内核映像,module表示以模块方式编译。
$ make config
——逐一遍历每个选项$ make menuconfig
——使用ncurse图形界面$ make gconfig
——使用图形界面工具$ make defconfig
——默认配置- 内核配置好后,配置项存放在源代码内核源码根目录的
.config
文件中,可以直接修改该文件,但修改后应该更新用$ make oldconfig
更新配置。 - 选项CONFIG_IKCONFIG_PROC把压缩过的内核配置文件放在
/proc/config.gz
中,如果当前内核启用了该选项,则可以直接克隆该配置。
- 编译内核
$ make
,2.6版本之前每次编译需要运行$make dep
。- 减少编译时的垃圾信息
$make > 文件名
: 把编译细节、警告、错误输出到指定文件。$make > /dev/null
:不记录任何编译信息
- 衍生多个编译作业:
$make -jn
,n为作业数目,每个CPU核心一个或两个作业。
- 删除内核:是如何安装的就选择相应的删除方法:
- rpm 删除法
rpm -qa | grep kernel* (查找所有linux内核版本)
rpm -e kernel-(想要删除的版本) - yum 删除法
yum remove kernel-(要删除的版本)
- 手动删除
删除/lib/modules/
目录下不需要的内核库文件
删除/usr/src/kernel/
目录下不需要的内核源码
删除/boot
目录下启动的核心档案和内核映像
更改grub的配置,删除不需要的内核启动列表
- rpm 删除法
安装内核补丁:
$patch -pl < 补丁路径
。内核源码的结构
目录 | 说明 |
---|---|
arch | 特定体系结构相关的代码 |
arch//mach-xxxx | 具体机器或主板相关的代码 |
arch//include/asm | 体系结构相关的头文件 |
arch//boot/dts设备数从3.0以后才有 | |
block | 块设备I/O层次 |
crypo | 加、解密库 |
COPYING | 版权声明。 |
CREDITS | Linux主要贡献者名单 |
Documentation,README | 内核源码文档及帮助文件 |
drivers | 设备驱动程序 |
firmware | 使用某些驱动程序而需要的设备固件 |
fs | VFS和各种文件系统 |
include | 内核头文件,需要提供给外部模块使用。 |
init | 内核引导和初始化 |
ipc | 进程间通信代码 |
kernel | 像调度程序这样的核心子系统 |
Kconfig, Kbuild, Makefile, scripts | 用于内核编译癿配置文件、脚本等。 |
lib | 内核函数库 |
mm | 内存管理子系统和VM |
MAINTAINERS | 维护者名单。 |
net | 网络子系统 |
samples | 示例,示范代码 |
scripts | 编译内核所用的脚本 |
security | Linux 安全模块 SElinux |
sound | 音频子系统 |
tools | 在Linux开发中用于性能测试、自测试等常用工具 |
usr | 早期用户空间代码(所谓的initramfs) |
virt | 虚拟化基础结构 |
2 内核开发的特点
无标准C库:不能使用标准C库和标准头文件。基本内核头文件位于
源码顶级目录下的include
目录,体系结构头文件位于源码顶级目录下的arch/体系结构/include
目录。使用GNU C,推荐用gcc 4.4或以后的版本来编译内核。
- 内联函数:内联函数在编译时会在它被调用的地方展开,减少了函数调用的开销,性能较好。但是,频繁的使用内联函数也会使代码变长,从而在运行时占用更多的内存。所以内联函数使用时最好要满足以下几点:函数较小,会被反复调用,对程序的时间要求比较严格。如:内联函数示例:
static inline void sample()
; - 分支声明:用unlikely标记绝少发生的分支和likely标记常发生的分支。如:
if (unlikely(error)) {};
和if (likely(success)) {};
- 内联汇编:内联汇编用于偏近底层或对执行时间严格要求的地方。如:
unsigned int low, high; asm volatile("rdtsc" : "=a" (low), "=d" (high));
- 内联函数:内联函数在编译时会在它被调用的地方展开,减少了函数调用的开销,性能较好。但是,频繁的使用内联函数也会使代码变长,从而在运行时占用更多的内存。所以内联函数使用时最好要满足以下几点:函数较小,会被反复调用,对程序的时间要求比较严格。如:内联函数示例:
没有内存保护:因为内核是最低层的程序,所以如果内核访问的非法内存,那么整个系统都会挂掉!!所以内核开发的风险比用户程序开发的风险要大。而且,内核中的内存是不分页的,每用一个字节的内存,物理内存就少一个字节。所以内核中使用内存一定要谨慎。
不使用浮点数:内核不能完美的支持浮点操作,使用浮点数时,需要人工保存和恢复浮点寄存器及其他一些繁琐的操作。
内核栈容积小且固定:内核栈的大小有编译内核时决定的,对于不用的体系结构,内核栈的大小虽然不一样,但都是固定的。查看内核栈大小的方法:
$ ulimit -a | grep "stack size"
。同步和并发:Linux是多用户的操作系统,所以必须处理好同步和并发操作,防止因竞争而出现死锁。
可移植性:Linux内核可用于不用的体现结构,支持多种硬件。所以开发时要时刻注意可移植性,尽量使用体系结构无关的代码。
版权声明:本文参考了《Linux 内核设计与艺术》。 未经作者允许,严禁用于商业出版,否则追究法律责任。网络转载请注明出处,这是对原创者的起码的尊重!!!