【Step1】Linux Kernel -基础

《Linux内核设计与实现.第3版》1-2章学习笔记

1. 获取内核源码

http://www.kernel.org

2. 内核版本命名规则

内核的版本号主要有四个数字组成。

【Step1】Linux Kernel -基础_第1张图片

从版本号: 偶数表示稳定版(可用于企业级环境),奇数表示开发版;

修订版本号: 包括BUG修正,新的驱动以及新的特性的追加;

稳定版本号: 关键性BUG的修改;

3. 单内核和微内核

原理 优势 劣势
单内核 整个内核都在一个大内核地址空间上运行。 简单、高效: 所有内核都在一个大的地址空间上,所以内核各个功能之间的调用和调用函数类似,几乎没有性能开销。 一个功能的崩溃会导致整个内核无法使用。
微内核 内核按功能被划分成各个独立的过程。每个过程独立的运行在自己的地址空间上。 安全: 内核的各种服务独立运行,一种服务挂了不会影响其他服务。 内核各个服务之间的调用涉及进程间的通信,比较复杂且效率低。

Linux内核是基于单内核的,但也具备微内核的一些特征:(体现了Linux实用至上的原则)

  1. 支持动态加载内核模块
  2. 支持对称多处理(SMP)
  3. 内核可以抢占(preemptive),允许内核运行的任务有优先执行的能力
  4. 不区分线程和进程

4. 内核源码的结构

目录 说明
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 虚拟化基础结构

5. 编译内核的方法

# 1.通过命令图形用户界面化配置,生成.config配置文件
$ sudo make menuconfig
# 2.内核编译
$ sudo make -j4
# 3.安装模块
$ sudo make modules_install
# 4.安装内核
$ sudo make install
# 5.reboot系统,重新选择内核版本,启动后通过以下指令查看内核版本
$ uname -a

修改ubuntu启动时选择内核:

# step1: 修改grub文件
$ sudo vim /etc/default/grub 
GRUB_DEFAULT=0
#GRUB_TIMEOUT_STYLE=hidden    # 1.屏蔽此处
GRUB_TIMEOUT=30               # 2.修改等待时间为30s
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""

# step2:更新grub配置
$ sudo update-grub

6. 内核开发的特点

  1. 无标准C库: 为了保证内核的小和高效,内核开发中不能使用C标准库,例如printk替代printf

  2. GNU C 扩展:

    • 内联函数: 内联函数在编译时会在它被调用的地方展开,减少了函数调用的开销,性能较好。

      ​ 但频繁的使用内联函数也会使代码变长,从而在运行时占用更多的内存。

      ​ **所以使用内联函数时要求:**函数较小,会被反复调用,对程序的时间要求比较严格。

      /*EG:*/ static inline void sample();
      
    • 内联汇编: 内联汇编用于偏近底层或对执行时间严格要求的地方。

      unsigned int low, high; /* low 和 high 分别包含64位时间戳的低32位和高32位 */
      asm volatile("rdtsc" : "=a" (low), "=d" (high));
      
    • 分支声明: 如果能事先判断一个if语句时经常为真还是经常为假,那么可以用unlikely和likely来优化这段判断的代码

      if (unlikely(error))  /* 如果error在绝大多数情况下为0(假) */
      if (likely(success))  /* 如果success在绝大多数情况下不为0(真) */
      
  3. 没有内存保护: 因为内核是最低层的程序,所以如果内核访问的非法内存,那么整个系统都会挂掉,所以内核开发的风险比用户程序开发的风险要大。

    ​ 而且,内核中的内存是不分页的,每用一个字节的内存,物理内存就少一个字节。所以内核中使用内存一定要谨慎。

  4. 不使用浮点数: 内核不能完美的支持浮点操作,使用浮点数时,需要人工保存和恢复浮点寄存器及其他一些繁琐的操作。

  5. 内核栈容积小且固定: 内核栈的大小有编译内核时决定的,对于不用的体系结构,内核栈的大小虽然不一样,但都是固定的。

    $ ulimit -a | grep "stack size"                # 查看内核栈大小的方法
    stack size              (kbytes, -s) 8192
    
  6. 同步和并发: Linux是多用户的操作系统,所以必须处理好同步和并发操作,防止因竞争而出现死锁。

  7. 可移植性: Linux内核可用于不用的体现结构,支持多种硬件。所以开发时要时刻注意可移植性,尽量使用体系结构无关的代码。


路虽远行则将至、事虽难做则必成
MrWang

你可能感兴趣的:(Linux,linux,gnu,ubuntu)