第2章 从内核出发

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图形界面
    • $ makegconfig——使用图形界面工具
    • $ 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的配置,删除不需要的内核启动列表
  • 安装内核补丁$patch -pl < 补丁路径

  • 内核源码的结构

目录 说明
arch 特定体系结构的代码
block 块设备I/O层
crypo 加密API
Documentation 内核源码文档
drivers 设备驱动程序
firmware 使用某些驱动程序而需要的设备固件
fs VFS和各种文件系统
include 内核头文件
init 内核引导和初始化
ipc 进程间通信代码
kernel 像调度程序这样的核心子系统
lib 通用内核函数
mm 内存管理子系统和VM
net 网络子系统
samples 示例,示范代码
scripts 编译内核所用的脚本
security Linux 安全模块
sound 语音子系统
usr 早期用户空间代码(所谓的initramfs)
tools 在Linux开发中有用的工具
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内核可用于不用的体现结构,支持多种硬件。所以开发时要时刻注意可移植性,尽量使用体系结构无关的代码。

猜你喜欢

转载自blog.csdn.net/liao20081228/article/details/78735039