《Linux内核设计与实现》读书笔记 第二章 从内核出发

1、获取内核源码

1. Git

  • git其实是一种开源的分布式版本控制工具。
  • Linux做为一个开源的内核,其源代码也能够用git下载和管理html

    - 获取最新提交到版本树的一个副本
      - $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
      - 下载代码后,更新本身的分支到最新分支
      - $ git pull

2.安装内核源代码

  • 压缩形式为bzip2:$ tar xvjf linux-x.y.z.tar.bz2
  • 压缩形式为zip:$ tar xvzf linux-x.y.z.tar.gzlinux

    关于参数:
      -x 解开.tar格式的文件
      -v 显示详细信息
      -j 使用bzip2程序
      -z 使用gzip程序
      -f 使用归档文件

3. 使用补丁

从内部源码树开始,运行$ patch -p1 < ../patch-x,y,zgit

2、内核源码结构

详见LINUX内核分析第三周学习总结:构造一个简单的LINUX系统MENUOS中第一部分:“Linux内核源码简介”。安全

目 录 描 述
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 虚拟化基础结构
  • COPYIN:内核许可证
  • CREDITS:开发者列表
  • MAINTAINTERS:维护者列表(维护内核子系统和驱动程序)

3、编译内核

1. 配置内核(关于make与config)

(1)相关

  • Makefile:根据配置的状况,构造出须要编译的源文件列表,而后分别编译,并把目标代码连接到一块儿,最终造成 Linux 内核二进制文件。
  • config.in:内核配置文件,给用户提供配置选择的功能。
  • 配置工具:包括配置命令解释器(make config)和配置用户界面(例如:make menuconfig:基于ncurse库的图形界面工具;make gconfig:基于gtk+的图形工具...)。
  • .config:用户用来存放内核配置后结果的文件。
  • 能够配置的各类选项:用CONFIG_FEATURE形式表示,其前缀为CONFIG。

(2)命令

  • make config:遍历全部配置项,并让用户选择
  • make deconfig:按默认的配置
  • make oldconfig:先将/boot目录下的配置文件写进.config文件中,采用的是注释的形式写进新增长的功能。
  • zcat /proc/config.gz > .config:配置选项CONFIG_IKCONFIG_PROC会把完整的压缩过的内核配置文件存放在/proc/config.gz中,再次编译时能够方便地克隆当前的配置。
  • make:默认的Makefile自动化编译。

2. 其它事项

  • 减小垃圾信息网络

    $ make > ../detritus
      #将错误报告和警告信息重定向到文件中
      $ make > /dev/null
      #将无用的输出信息重定向到/dev/null中
    
      - /dev/null:空设备,输入的信息直接丢弃
  • 衍生多个编译做业:make程序能把编译过程拆分红多个并行的做业。其中每一个做业独立并发地运行,有助于加快多处理器系统上的编译过程,也有利于改善处理器的利用率。默认状况下,make只衍生一个做业。并发

    $ make -jn
      #以多个做业编译内核
    
      - j:指定同时执行多任务
      - n:要衍生出的做业数

3. 安装新内核

make modules_install
#把全部已编译的模块安装到正确的主目录/lib/modules下
  • System.map文件:编译时在内核代码树的根目录下建立的符号对照表。用来将内核符号与它们的起始地址对应起来。

4、内核开发特色

1. 无libc库/标准头文件

  • 缘由:(速度与大小)保证内核高效和简练。
  • 内核源代码文件不能包含外部头文件。
    • 基本头文件:内核源代码顶级目录下的include
    • 体系结构相关头文件:内核源代码树的arch/<architecture>/include/asm目录下
  • printk()函数:把格式化好的字符串拷贝到内核日志缓冲区上,syslog程序能够经过读取该缓冲区来获取内核信息。

2. 必须使用GNU C

什么是GNU?GNU是一种操做系统,GNU提供的C编译器就是咱们以前使用的gcc。

(1)内联函数

static inline void wolf(unsigned long tail_size);
- static:关键字
- inline:用于限定关键字
  • 内联函数:编译时在它被调用的地方展开。
    • 优势:减小了函数调用的开销,性能较好。
    • 缺点:频繁的使用内联函数也会使代码变长,从而在运行时占用更多的内存。
  • 定义内联函数特色:时间要求高,自己长度较短的函数。异步

  • 使用以前就要定义好内联函数,通常在头文件中定义。分布式

  • 为了类型安全和易读性,优先使用内联函数而不是复杂的宏。函数

(2)内联汇编

unsigned int low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
/* low 和 high 分别包含64位时间戳的低32位和高32位 */
- asm:嵌入汇编代码
- volatile:不优化
  • 汇编语言用于偏近底层或对执行时间严格要求的地方。

(3)分支声明

/* 若是error在绝大多数状况下为0(假) */
if (unlikely(error)) {
    /* ... */
}

/* 若是success在绝大多数状况下不为0(真) */
if (likely(success)) {
    /* ... */
}
  • 对于条件选择语句,在一个条件常常/不多出现时,编译器可经过gcc内建的一条指令对条件分支选择进行优化。
  • 内核把这条指令封装成了宏。

3. 没有内存保护机制

  • 内核本身非法访问内存的风险
  • 内核中的内存都不分页:每用掉一个字节,物理内存都减小一个

4. 难以执行浮点运算

  • 使用浮点数时,须要人工保存和恢复浮点寄存器及其余一些繁琐的操做。
  • 不建议使用

5. 每一个进程只有一个很小的定长堆栈

  • 内核栈的大小是编译内核时决定的,对于不用的体系结构,内核栈的大小不同,但都是固定的。(不像用户空间的栈能够动态增加)

6. 必须时刻注意同步和并发

  • 缘由:
    • Linux是抢占多任务操做系统
    • 内核支持对称多处理器系统(SMP)
    • 中断异步到来
    • 内核能够抢占
  • 经常使用解决方法:自旋锁和信号量

7. 考虑可移植性的重要性

  • 须要保持的特色:大部分C语言代码与体系结构无关。

5、总结:关于Linux内核的结构与特色

1. 版本控制

  • 我最先接触git是刚开始使用实验楼的时候,实验楼中的代码保存须要用到其中“个人代码库”功能,实际上就是最简单的git。
  • Linux内核这种开源的代码以及不少项目使用git进行版本控制与协做都是挺方便的。
  • 网上有不少教程能够参考,感受这个比较全面:Git教程,能够在一些网站上建立本身的代码库,好比:git.oschina,操做过就会发现仍是比较简单的。

2. 依据结构和特色的开发

  • 通读本章以后感受Linux内核的不少要求与通常的项目实际上是差很少的,它的这些基本结构、开发的特色,对于理解它各个部分的工做过程是颇有帮助的。

参考资料1:《Linux内核设计与实现》(原书第三版)
参考资料2:make config 解惑工具

相关文章
相关标签/搜索