《Linux内核设计与实现》读书笔记——第一二章

《Linux内核设计与实现》读书笔记——第一二章

第一章 Linux内核简介

1.1 Unix的历史

  • 简洁:仅提供系统调用并有一个非常明确的设计目的。
  • 抽象:Unix中绝大部分东西都被当做文件,这种抽象使对数据和对设备的操作是通过一套相同的系统调用接口来进行的(open()、read()、write()、lseek()、close())。
  • 可移植:使用C语言编写,使其在各种硬件体系架构面前都具备令人惊异的移植能力。
  • 进程创建迅速:有独特的fork()系统调用,一次执行保质保量地完成一个任务。简单的进程间通信元语把单一目的的程序方便地组合在一起,这种策略和机制分离的理念确保了Unix系统具备清晰的层次化结构。
  • Unix已经发展成一个支持抢占式多任务、多线程、虚拟内存、换页、动态链接和TCP/IP网络的现代化操作系统。

1.2 追寻Linus足迹:Linux简介

  1. Linux是类Unix系统,但不是Unix。Linux没有直接使用Unix的源代码,但它没有抛弃Unix的设计目标并且保证了应用程序编程接口的一致。
  2. Linux内核是自由公开软件
  3. Linux用途广泛,Linux系统的基础是内核、C库、工具集和系统的基本工具。一般情况下Linux这个词汇主要还是指内核。

1.3 操作系统和内核简介

处理器在任何指定时间点上的活动范围可以概括为下列三者之一:

  • 运行于内核空间,处于进程上下文,代表某个特定的进程执行。
  • 运行于内核空间,处于中断上下文,与任何进程无关,处理某个特定的中断。
  • 运行于用户空间,执行用户进程。

1.4 Linux内核和传统Unix内核的比较

1.操作系统可分为两大阵营:单内核、微内核。第三大阵营是外内核(主要用于科研系统)。

2.Linux是一个单内核,至今Linux是模块化的、多线程的以及内核本身可调度的操作系统。

3.Linux内核和传统Unix内核的差异:

  • Linux支持动态加载内核模块。
  • Linux支持对称多处理(SMP)机制,传统的Unix不支持。
  • Linux内核可以抢占,允许内核运行的任务有优先执行的能力。
  • Linux内核不区分线程和其他的一般进程。
  • Linux提供具有设备类的面向对象的设备模型、热插拔事件,以及用户空间的设备文件系统。
  • Linux忽略了一些被认为是设计的很拙劣的Unix特性和难以实现的过时标准。
  • Linux体现了自由的精髓。

1.5 Linux内核版本

1.Linux内核有两种:稳定的(具有工业级的强度,可以广泛应用和部署)、处于开发中的。

2.Linux命名机制:

如果版本号是偶数,则内核是稳定版;如果是奇数,内核就是开发版。

1.6 Linux内核开发者社区

这个社区最重要的论坛:Linux kernel mailing list(lkml)

第二章 从内核出发

2.1 获取内核源码

  • 使用Git

    git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
    git pull # 更新分支到Linux的最新分支
    
  • 安装内核源代码(如果使用git获取就不需要下载压缩文件。)
    tar xvjf linux-x.y.z.tar.bz2
    或者
    tar xvzf linux-x.y.z.tar.gz
    

注意:内核源代码一般安装在/usr/src/linux目录下,即使在安装新内核时,/usr/src/linux目录应当保证原封不动。

  • 使用补丁

    patch -p1 < ../patch-x.y.z

2.2 内核源码树

内核源码树由很多目录组成,而大多数目录又包含更多的子目录。源码树的根目录及其子目录如表所示。

目录  描述
arch    特定体系结构的源码
crypto  Crypto API
Documentation   内核源码文档
drivers 设备驱动程序
fs  VFS和各种文件系统
include 内核头文件
init    内核引导和初始化
ipc 进程间通信代码
kernel  像调度程序这样的核心子系统
lib 通用内核函数
mm  内存管理子系统和VM
net 网络子系统
scripts 编译内核所用的脚本
security    Linux安全模块
sound   语音子系统
usr 早期用户空间代码 (所谓的 initramfs)

2.3 编译内核

2.3.1 配置内核

1.配置项

  • 二选一:yes 或者 no
  • 三选一:yes 或者 no 或者 module(module意味着该配置被选定了,以模块生成。驱动程序一般都用三选一的配置项)
字符页面的命令行工具:
make config

图形界面工具:
make menuconfig

基于默认配置为体系结构创建一个配置:
make defconfig 

验证和更新配置:
make oldconfig

2.3.2 减少编译的垃圾信息

  • 我们希望在编译时看到错误和警告信息,但对匆匆掠过屏幕的垃圾信息不感兴趣,可以用下面的技巧来实现愿望:
    make > some_other_file
  • 一旦需要查看编译的输出信息,可以查看这个文件。不过,因为错误和警告都会在屏幕上显示,所以你需要看这个文件的可能性不大。事实上,我只不过敲入如下命令
    $ make > /dev/null
    这就把无用的输出信息重定向到永无返回值的黑洞/dev/null。

2.3.3 衍生多个编译作业

  • 为了以多个作业编译内核,使用以下命令:
    $ make -jn
  • 这里,n是要衍生的作业数,在实际中,每个处理器上一般衍生一个或者两个作业。例如,在一个双处理器上,可以输入如下命令:
    $ make –j4

2.3.4 安装新内核

  • 模块的安装是自动的,也是独立于体系结构的。以root身份,只要运行:
    % make modules_install
    就可以把所有已编译的模块安装到正确的主目录/lib下。

2.4 内核开发的特点

Linux内核编程与用户空间内应用程序开发的差异

  • Linux内核编程时不能访问C库
  • Linux内核编程时必须使用GNU C
  • Linux内核编程时缺乏像用户空间那样的内存保护机制。
  • Linux内核编程时浮点数很难使用。
  • 内核只有一个很小的定长堆栈。
  • 由于内核支持异步中断、抢占式和SMP,因此必须时刻注意同步和并发。
  • 要考虑可移植性的重要性。

2.4.1 无libc库抑或无标准头文件

  • 大部分常用的C库函数在内核中都已经得到实现了。比如说操作字符串的函数组就位于lib/string.c文件中。只要包含<linux/string.h>头文件,就可以使用它们。
  • 在所有没有实现的函数中,最著名的就数printf()函数了。内核代码虽然无法调用printf(),但它可以调用printk()函数。

2.4.2 GNU C

内核开发者使用的C语言涵盖了ISO C995标准和GNU C扩展特性。

  • 内联(inline)函数
  • 内联汇编
  • 分支声明

2.4.3 没有内存保护机制

  • 如果一个用户程序试图进行一次非法的内存访问,内核会发现这个错误,发送 SIGSEGV,并结束整个进程。
  • 内核中发生的内存错误会导致oops,这是内核中出现的最常见的一类错误。
  • 内核中的内存都不分页。

2.4.4 不要轻易在内核中使用浮点数

  • 在执行浮点指令时到底会做些什么,因体系结构不同,内核的选择也不同,但是,内核通常捕获陷阱并做相应处理。
  • 和用户空间进程不同,内核并不能完美地支持浮点操作,因为它本身不能陷入

2.4.5 容积小而固定的栈

  • 内核栈的准确大小随体系结构而变。在x86上,栈的大小在编译时配置,可以是4KB也可以是8KB。
  • 从历史上说,内核栈的大小是两页,这就意味着,32位机的内核栈是8KB,而64位机是16KB,这是固定不变的。
  • 每个处理器都有自己的栈。

2.4.6 同步和并发

  • Linux是抢占多任务操作系统。内核的进程调度程序即兴对进程进行调度和重新调度。内核必须对这些任务同步。
  • Linux内核支持多处理器系统。
  • 中断是异步到来的,完全不顾及当前正在执行的代码。
  • Linux内核可以抢占。

2.4.7 可移植性的重要性

  • Linux是一个可移植的操作系统,
  • 必须把体系结构相关的代码从内核代码树的特定目录中适当地分离出来。
时间: 2024-10-28 10:03:23

《Linux内核设计与实现》读书笔记——第一二章的相关文章

Linux内核设计与实现读书笔记——第三章

Linux内核设计与实现读书笔记——第三章 进程管理 20135111李光豫 3.1进程 1.进程即处于执行期的程序,并不局限于一个可执行的代码,是处于执行期程序以及其相关资源的总称. 2.Linux系统中,对于进程和线程并没有明显的区分,线程是一种特殊的进程. 3.Linux系统中,常用fork()进程创建子进程.调用fork()进程的成之为其子进程的父进程. 4.fork()继承实际上由clone()系统调用实现.最后通过exit()退出执行. 3.2任务描述符及任务结构 1.任务队列实质上

Linux内核设计与实现 读书笔记 转

Linux内核设计与实现  读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://blog.csdn.net/yrj/article/category/718110 Linux内存管理和性能学习笔记(一) :内存测量与堆内存 第一篇 内存的测量 2.1. 系统当前可用内存 # cat /proc/meminfoMemTotal:        8063544 kBMemFree:       

Linux内核设计与实现 读书笔记

第三章 进程管理 1. fork系统调用从内核返回两次: 一次返回到子进程,一次返回到父进程 2. task_struct结构是用slab分配器分配的,2.6以前的是放在内核栈的栈底的:所有进程的task_struct连在一起组成了一个双向链表 3. 2.6内核的内核栈底放的是thread_info结构,其中有指向task_struct的指针: 4. current宏可以找到当前进程的task_struct:X86是通过先找到thread_info结构,而PPC是有专门的寄存器存当前task_s

Linux内核设计与实现读书笔记——第十八章

第18章 调试 调试工作艰难是内核级开发区别于用户级开发的一个显著特点,相比于用户级开发,内核调试的难度确实要艰苦得多.更可怕的是,它带来的风险比用户级别更高,内核的一个错误往往立刻就能让系统崩溃. 18.1 准备开始 一个bug.听起来很可笑,但确实需要一个确定的bug.如果错误总是能够重现的话,那对我们会有很大的帮助(有一部分错误确实如此).然而不幸的是,大部分bug通常都不是行为可靠而且定义明确的. 一个藏匿bug的内核版本.如果你知道这个bug最早出现在哪个内核版本中那就再理想不过了.

《Linux内核设计与实现读书笔记之系统调用》

1.系统调用的概念 为了和用户空间上运行的进程进行交互,内核提供了一组借口.透过该接口,应用程序可以访问硬件设备和其他操作系统资源.这组借口在应用程序和内核之间扮演着使者的角色.同时,这组接口也保证了系统稳定可靠,避免应用程序肆意妄行,惹出麻烦.Linux系统的系统调用作为C库的一部分提供,其调用过程中的实例如下图所示: 从程序员的角度看,系统调用无关紧要,他们只需要跟API打交道就可以了.相反,内核只跟系统调用打交道,库函数以及应用程序是怎么使用系统调用不是内核所关心的. 2.系统调用的处理程

Linux内核设计与实现——读书笔记2:进程管理

1.进程: (1)处于执行期的程序,但不止是代码,还包括各种程序运行时所需的资源,实际上进程是正在执行的 程序的实时结果. (2)程序的本身并不是进程,进程是处于执行期的程序及其相关资源的总称. (3)两个或两个以上并存的进程可以共享诸如打开的文件,地址空间等共享资源. (4)在Linux中通常是调用fork()系统函数的结果,通过复制一个现有的进程来创建一个新的子进程. fork()系统函数 (5)fork在这个系统调用结束时,在同一位置上返回两次(从内核返回两次),父进程恢复运行,子进程开始

《Linux内核设计与实现》笔记-1-linux内核简介

一.Linux内核相对于传统的UNIX内核的比较: (1):Linux支持动态内核模块.尽管Linux内核也是整体式结构,可是允许在需要的时候动态哦卸除(rmmod xxx)和加载内核模块(insmod  xxx.ko). (2):Linux支持对称多处理(SMP)机制,尽管许多UNIX的变体也支持SMP,但是传统的UNIX并不支持这种机制. (3):Linux内核可以抢占(preemptive).在Linux 2.4以及以前的版本都是不支持内核抢占的,在Linux 2.6以及以后就支持了. (

《Linux内核设计与实现》第一、二章学习笔记

<Linux内核设计与实现>第一.二章学习笔记 姓名:王玮怡  学号:20135116 第一章 Linux内核简介 一.关于Unix ——一个支持抢占式多任务.多线程.虚拟内存.换页.动态链接和TCP/IP网络的现代化操作系统 1.主要发展过程   1969年,贝尔实验室的程序员们设计了一个文件系统原型,最终发展演化成了Unix 1971年,Unix被移植到PDP-11型机中 1973年,整个Unix系统使用C语言进行重写,为后来Unix系统的广泛移植铺平了道路 Unix第六版(V6)被贝尔实

《Linux内核设计与实现》笔记——内核同步简介

相关概念 竞争条件 多个执行线程(进程/线程/中断处理程序)并发(并行)访问共享资源,因为执行顺序不一样造成结果不一样的情况,称为竞争条件(race condition) 举例说明 #include<thread> using namespace std; int i = 0; void thread1(){ //for(int x=0;x<100000;x++) i++; } void thread2(){ //for(int x=0;x<100000;x++) i++; } i