zoukankan      html  css  js  c++  java
  • 《Linux内核设计与实现》读书笔记 第二章 从内核出发

    一、获取内核源码

    1. Git

    • git实际上是一种开源的分布式版本控制工具。

    • Linux作为一个开源的内核,其源代码也可以用git下载和管理

        - 获取最新提交到版本树的一个副本
        - $ 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.gz

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

    3. 使用补丁

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

    二、内核源码结构

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

    目 录描 述
    arch特定体系结构的代码
    block块设备I/O层
    crypo加密API
    Documentation内核源码文档
    drivers设备驱动程序
    firmware使用某些驱动程序而需要的设备固件
    fsVFS和各种文件系统
    include内核头文件
    init内核引导和初始化
    ipc进程间通信代码
    kernel像调度程序这样的核心子系统
    lib同样内核函数
    mm内存管理子系统和VM
    net网络子系统
    samples示例,示范代码
    scripts编译内核所用的脚本
    securityLinux 安全模块
    sound语音子系统
    usr早期用户空间代码(所谓的initramfs)
    tools在Linux开发中有用的工具
    virt虚拟化基础结构
    • COPYIN:内核许可证
    • CREDITS:开发者列表
    • MAINTAINTERS:维护者列表(维护内核子系统和驱动程序)

    三、编译内核

    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文件:编译时在内核代码树的根目录下创建的符号对照表。用来将内核符号与它们的起始地址对应起来。

    四、内核开发特点

    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语言代码与体系结构无关。

    五、总结:关于Linux内核的结构与特点

    1. 版本控制

    • 我最早接触git是刚开始使用实验楼的时候,实验楼中的代码保存需要用到其中“我的代码库”功能,实际上就是最简单的git。
    • Linux内核这种开源的代码以及很多项目使用git进行版本控制与协作都是挺方便的。
    • 网上有很多教程可以参考,感觉这个比较全面:Git教程,可以在一些网站上创建自己的代码库,比如:git.oschina,操作过就会发现还是比较简单的。

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

    • 通读本章之后感觉Linux内核的很多要求与一般的项目其实是差不多的,它的这些基本结构、开发的特点,对于理解它各个部分的工作过程是很有帮助的。

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

  • 相关阅读:
    poj 3040 Allowance
    poj 2393 Yogurt factory
    【BZOJ1833】数字计数(ZJOI2010)-数位DP
    【BZOJ4820】硬币游戏(SDOI2017)-概率+高斯消元+KMP
    【BZOJ3626】LCA(LNOI2014)-树链剖分+离线处理
    【BZOJ4817】树点涂色(SDOI2017)-LCT+LCA+线段树
    【BZOJ1135】LYZ(POI2009)-线段树+Hall定理
    【CF392D】Three Arrays-set+multiset
    【51Nod1688】LYKMUL-线段树+乘法原理
    【BZOJ2956】模积和-数论分块
  • 原文地址:https://www.cnblogs.com/hyq20135317/p/5277142.html
Copyright © 2011-2022 走看看