
- 软件授权
- 免费
- 软件名称
- Linux内核
- 发明者
- Linus Torvalds
- 使用时间
- 1991年
- 软件语言
- C语言
-
2021-05-10 06:54:19
前面总结了关于Linux内核结构的学习,接下来我们一起学习Linux内核源代码。
第一:多版本的内核源代码
对不同的内核版本,系统调用一般是相同的。新版本也许可以增加一个新的系统调用,但旧的系统调用将依然不变,这对于保持向后兼容是非常必要的—一个新的内核版本不能打破常规的过程。在大多数情况下,设备文件将仍然相同,而另一方面,版本之间的内部接口有所变化。
Linux内核源代码有一个简单的数字系统,任何偶数内核(如2.0.30)是一个稳定的版本,而奇数内核(如2.1.42)是正在发展中的内核。这本书是基于稳定的2.4.16
源代码树。发展中的内核总是有最新的特点,支持最新的设备,尽管它们还不稳定,也不是你所想要的,但它们是发展最新而又稳定的内核的基础。
目前,较新而又稳定的内核版本是2.2.x和2.4.x,因为版本之间稍有差别,因此,如果你想让一个新驱动程序模块既支持2.2.x,也支持2.4.x,就需要根据内核版本对模块进行条件编译。
对内核源代码的修改是以补丁文件的形式发布的。patch实用程序用来对内核源文件进行一系列的修订,例如,如果你有2.4.9内核源代码,而你想移到2.4.16,你可以获得2.4.16的补丁文件,应用patch来修订2.4.9源文件。例如:
$ cd /usr/src/linux
$ patch -p1 < patch-2.4.16
第二:Linux内核源代码的结构
Linux内核源代码位于/usr/src/linux目录下,其结构分布如图1.3所示,每一个目录或子目录可以看作一个模块,其目录之间的连线表示“子目录或子模块”的关系。下面是对每一个目录的简单描述。
include/子目录包含了建立内核代码时所需的大部分包含文件,这个模块利用其它模块重建内核。
init/ 子目录包含了内核的初始化代码,这是内核开始工作的起点。
arch/子目录包含了所有硬件结构特定的内核代码,如图1.3,arch/ 子目录下有i386和alpha模块等等。
drivers/ 目录包含了内核中所有的设备驱动程序,如块设备,scsi 设备驱动程序等等。
fs/ 目录包含了所有文件系统的代码,如:ext2, vfat模块的代码等等。
net/ 目录包含了内核的连网代码。
mm/ 目录包含了所有的内存管理代码。
ipc/ 目录包含了进程间通信的代码。
kernel/
目录包含了主内核代码
图1.3 显示了八个目录,即 init, kernel, mm, ipc,
drivers, fs, arch 及 net 的包含文件都在"include/" 目录下。在Linux内核中包含了 drivers, fs, arch及 net 模块,这就使得Linux内核既不是一个层次式结构,也不是一个微内核结构,而是一个“整体式”结构。因为系统调用可以直接调用内核层,因此,该结构使得整个系统具有较高的性能,其缺点是内核修改起来比较困难,除非遵循严格的规则和编码标准。
在图1.3中所显示的模块结构,代表了一种工作分配单元,利用这种结构,我们期望Linus
Torvalds能维护和增强内核的核心服务,即,init/, kernel/, mm/及 ipc/,其它的模块drivers, fs, arch及net 也可以作为工作单元,例如,可以分配一组人对块文件系统进行维护和进一步的开发,而另一组人对scsi文件系统进行完善。图1.3类似于Linux的自愿者开发队伍一起工作来增强和扩展整个系统的框架。
Linux源代码的分布结构
第三: 从何处开始阅读源代码
像Linux内核这样庞大而复杂的程序看起来确实让人望而生畏,它象一个很大的球,没有起点和终点。在读源代码的过程中,你会遇到这样的情况,当读到内核的某一部分时又会涉及到其它更多的文件,当返回到原来的地方想继续往下读时,又忘了原来读的内容。在internet上,很多人为此付出了很大的努力,制作出了源代码导航器,这为源代码阅读提供了良好的条件,站点为:,下面给出阅读源代码的一些线索。
1. 系统的启动和初始化
在基于Intel的系统上,当 loadlin.exe 或 LILO把内核装入到内存并把控制权传递给内核时,内核开始启动。关于这一部分,看arch/i386/kernel/head.S
,head.S进行特定结构的设置,然后跳转到init/main.c的main()例程。
2. 内存管理
内存管理的代码主要在/mm,但特定结构的代码在arch/*/mm。缺页中断处理的代码在mm/memory.c
,而内存映射和页高速缓存器的代码在mm/filemap.c。缓冲器高速缓存是在mm/buffer.c 中实现,而交换高速缓存是在mm/swap_state.c
和 mm/swapfile.c中实现。
3. 内核
内核中,特定结构的代码在arch/*/kernel,调度程序在kernel/sched.c,fork的代码在kernel/fork.c,task_struct
数据结构在 include/linux/sched.h中。
4.
PCI
PCI 伪驱动程序在 drivers/pci/pci.c ,其定义在include/linux/pci.h。每一种结构都有一些特定的
PCI BIOS 代码, Intel的在arch/alpha/kernel/bios32.c。
5. 进程间通信
所有System V IPC 对象权限都包含在 ipc_perm 数据结构中,这可以在 include/linux/ipc.h中找到。 System V 消息是在
ipc/msg.c中实现, 共享内存在 ipc/shm.c中,信号量在
ipc/sem.c中,管道在 ipc/pipe.c中实现。
6. 中断处理
内核的中断处理代码是几乎所有的微处理器所特有的。中断处理代码在 arch/i386/kernel/irq.c中,其定义子在
include/asm-i386/irq.h中。
7. 设备驱动程序
Linux内核源代码的很多行是设备驱动程序。Linux设备驱动程序的所有源代码都保存在/driver,根据类型可进一步划分为:
/block
块设备驱动程序如ide(在ide.c)。如果你想看包含文件系统的所有设备是如何被初始化的,你应当看drivers/block/genhd.c中的device_setup(),device_setup()不仅初始化了硬盘,当一个网络安装nfs文件系统时,它也初始化网络。块设备包含了基于IDE和SCSI的设备。
/char
这是看字符设备(如tty,串口及鼠标等)驱动程序的地方。
/cdrom
Linux的所有CDROM代码都在这儿,如在这儿可以找到Soundblaster
CDROM的驱动程序。注意ide CD的驱动程序是 ide-cd.c,放在drivers/block,SCSI CD的驱动程序是scsi.c,放在drivers/scsi。
/pci
这是PCI伪驱动程序的源代码,在这里可以看到PCI子系统是如何被映射和初始化的。
/scsi
在这里可以找到所有的SCSI代码及Linux所支持的scsi设备的所有设备驱动程序。
/net
在这里可以找到网络设备驱动程序,如DECChip 21040 PCI 以太网驱动程序在tulip.c中。
/sound
这是所有声卡驱动程序的所在地。
8. 文件系统
EXT2 文件系统的源代码全部在 fs/ext2/ 目录下,而其数据结构的定义在 include/linux/ext2_fs.h, ext2_fs_i.h 及
ext2_fs_sb.h中。 虚拟文件系统的数据结构在 include/linux/fs.h中描述,而代码是在fs/*中。 缓冲区高速缓存与更新内核的守护进程的实现是在
fs/buffer.c中 。
8. 网络
网络代码保存在/net中,大部分的include文件在include/net下,BSD套节口代码在net/socket.c中,IP
第4版本的套节口代码在net/ipv4/af_inet.c。一般的协议支持代码(包括sk_buff 处理例程)在net/core下,TCP/IP联网代码在net/ipv4下,网络设备驱动程序在/drivers/net下。
9. 模块
内核模块的代码部分在内核中,部分在模块包中,前者全部在kernel/modules.c中,而数据结构和内核守护进程kerneld的信息分别在include/linux/module.h和include/linux/kerneld.h
中。如果你想看ELF目标文件的结构,它位于include/linux/elf.h中。
网,更多精彩阅读:
更多相关内容 -
奔跑吧Linux内核基于Linux4.x内核源代码问题分析.zip
2019-03-17 15:26:14奔跑吧Linux内核基于Linux4.x内核源代码问题分析,要下的速度了,很快就删了 -
ARM Linux内核源码剖析.pdf
2017-11-03 21:49:43ARM Linux内核源码剖析.pdfARM Linux内核源码剖析.pdfARM Linux内核源码剖析.pdfARM Linux内核源码剖析.pdf 完整书签 -
Linux内核视频教程(70G百度网盘资源)
2018-07-27 14:32:43Linux 内核相关视频教程下载链接(70G左右的百度网盘资源)。 -
Linux内核设计与实现_第三版_中文版pdf
2019-01-27 21:54:07Linux内核设计与实现_第三版_中文版的 pdf,带目录结构 -
linux内核技术手册中英文版
2015-05-31 09:27:39《Linux 内核技术手册》由顶尖的Linux内核开发及维护人员编写,它详尽描述了内核的配置和构建——这对于系统管理员和开发人员而言是一个至关重要的工作。由于没有一个Linux发行套件能够提供完全符合用户要求的Linux... -
【Linux 内核】Linux 内核源码结构 ( 下载 Linux 内核源码 | 使用 VSCode 阅读 Linux 内核源码 )
2022-03-24 10:20:49一、下载 Linux 内核源码、 二、使用 VSCode 阅读 Linux 内核源码
一、下载 Linux 内核源码
参考 【Linux 内核】编译 Linux 内核 ① ( 下载指定版本的 Linux 内核源码 | Linux 内核版本号含义 | 主版本号 | 次版本号 | 小版本号 | 稳定版本 ) 博客 , 下载 Linux 5.6.18 版本的内核源码 ;
- 5.x 内核源码下载地址 : https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/
- Linux 内核 5.6.18 版本 : https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.6.18.tar.gz
下载完 Linux 源码后 , 如果在 Windows 系统中解压 , 需要使用管理员权限在 命令行终端 中解压 , 参考 【错误记录】解压 Linux 内核报错 ( Can not create symbolic link : 客户端没有所需的特权 | Windows 中配置 7z 命令行执行解压操作 ) 博客 ;
不同版本的 Linux 内核 区别 :
- 系统调用 : 其系统调用是相同的 , 新的版本可能会增加新的系统调用 ;
- 设备文件 : 各内核版本的设备文件都是相同的 , 但是 内部接口 可能不同 ;
二、使用 VSCode 阅读 Linux 内核源码
参考 【开发环境】安装 Visual Studio Code 开发环境 ( 下载 Visual Studio Code 安装器 | Visual Studio Code ) 博客 , 安装 VSCode 软件 ;
打开 VSCode , 选择 " 菜单栏 / 文件 / 打开文件夹 " 选项 ,
选择 Linux 内核源码目录 , 点击 " 选择文件夹 " 按钮 ,
此时就可以在 VSCode 中阅读 Linux 内核源码 ;
-
ARM Linux内核源码剖析_ PDF电子书下载 带书签目录 完整版
2018-06-13 19:01:04ARM Linux内核源码剖析_ PDF电子书下载 带书签目录 完整版 -
一文看懂Linux内核!Linux内核架构和工作原理详解
2021-01-29 15:14:27linux内核相关视频解析: 5个方面分析linux内核架构,让你对内核不再陌生 90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc的原理 手把手带你实现一个Linux内核文件系统 简介 作用是将应用层序的请求传递...linux内核相关视频解析:
5个方面分析linux内核架构,让你对内核不再陌生
90分钟了解Linux内存架构,numa的优势,slab的实现,vmalloc的原理
手把手带你实现一个Linux内核文件系统简介
作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。目前支持模块的动态装卸(裁剪)。Linux内核就是基于这个策略实现的。Linux进程1.采用层次结构,每个进程都依赖于一个父进程。内核启动init程序作为第一个进程。该进程负责进一步的系统初始化操作。init进程是进程树的根,所有的进程都直接或者间接起源于该进程。virt/ ---- 提供虚拟机技术的支持。
Linux内核预备工作
理解Linux内核最好预备的知识点:
懂C语言
懂一点操作系统的知识
熟悉少量相关算法
懂计算机体系结构Linux内核的特点:
结合了unix操作系统的一些基础概念
Linux内核的任务:
1.从技术层面讲,内核是硬件与软件之间的一个中间层。作用是将应用层序的请求传递给硬件,并充当底层驱动程序,对系统中的各种设备和组件进行寻址。
2.从应用程序的层面讲,应用程序与硬件没有联系,只与内核有联系,内核是应用程序知道的层次中的最底层。在实际工作中内核抽象了相关细节。
3.内核是一个资源管理程序。负责将可用的共享资源(CPU时间、磁盘空间、网络连接等)分配得到各个系统进程。
4.内核就像一个库,提供了一组面向系统的命令。系统调用对于应用程序来说,就像调用普通函数一样。
内核实现策略:
1.微内核。最基本的功能由中央内核(微内核)实现。所有其他的功能都委托给一些独立进程,这些进程通过明确定义的通信接口与中心内核通信。
2.宏内核。内核的所有代码,包括子系统(如内存管理、文件管理、设备驱动程序)都打包到一个文件中。内核中的每一个函数都可以访问到内核中所有其他部分。目前支持模块的动态装卸(裁剪)。Linux内核就是基于这个策略实现的。
哪些地方用到了内核机制?
1.进程(在cpu的虚拟内存中分配地址空间,各个进程的地址空间完全独立;同时执行的进程数最多不超过cpu数目)之间进行通 信,需要使用特定的内核机制。
2.进程间切换(同时执行的进程数最多不超过cpu数目),也需要用到内核机制。
进程切换也需要像FreeRTOS任务切换一样保存状态,并将进程置于闲置状态/恢复状态。
3.进程的调度。确认哪个进程运行多长的时间。
Linux进程
1.采用层次结构,每个进程都依赖于一个父进程。内核启动init程序作为第一个进程。该进程负责进一步的系统初始化操作。init进程是进程树的根,所有的进程都直接或者间接起源于该进程。
2.通过pstree命令查询。实际上得系统第一个进程是systemd,而不是init(这也是疑问点)
3.系统中每一个进程都有一个唯一标识符(ID),用户(或其他进程)可以使用ID来访问进程。
Linux内核源代码的目录结构
Linux内核源代码包括三个主要部分:
内核核心代码,包括第3章所描述的各个子系统和子模块,以及其它的支撑子系统,例如电源管理、Linux初始化等
其它非核心代码,例如库文件(因为Linux内核是一个自包含的内核,即内核不依赖其它的任何软件,自己就可以编译通过)、固件集合、KVM(虚拟机技术)等
编译脚本、配置文件、帮助文档、版权说明等辅助性文件
使用ls命令看到的内核源代码的顶层目录结构,具体描述如下。
include/ ---- 内核头文件,需要提供给外部模块(例如用户空间代码)使用。
kernel/ ---- Linux内核的核心代码,包含了3.2小节所描述的进程调度子系统,以及和进程调度相关的模块。
mm/ ---- 内存管理子系统(3.3小节)。
fs/ ---- VFS子系统(3.4小节)。
net/ ---- 不包括网络设备驱动的网络子系统(3.5小节)。
ipc/ ---- IPC(进程间通信)子系统。
arch// ---- 体系结构相关的代码,例如arm, x86等等。
arch//mach- ---- 具体的machine/board相关的代码。
arch//include/asm ---- 体系结构相关的头文件。
arch//boot/dts ---- 设备树(Device Tree)文件。init/ ---- Linux系统启动初始化相关的代码。
block/ ---- 提供块设备的层次。
sound/ ---- 音频相关的驱动及子系统,可以看作“音频子系统”。
drivers/ ---- 设备驱动(在Linux kernel 3.10中,设备驱动占了49.4的代码量)。lib/ ---- 实现需要在内核中使用的库函数,例如CRC、FIFO、list、MD5等。
crypto/ ----- 加密、解密相关的库函数。
security/ ---- 提供安全特性(SELinux)。
virt/ ---- 提供虚拟机技术(KVM等)的支持。
usr/ ---- 用于生成initramfs的代码。
firmware/ ---- 保存用于驱动第三方设备的固件。samples/ ---- 一些示例代码。
tools/ ---- 一些常用工具,如性能剖析、自测试等。Kconfig, Kbuild, Makefile, scripts/ ---- 用于内核编译的配置文件、脚本等。
COPYING ---- 版权声明。
MAINTAINERS ----维护者名单。
CREDITS ---- Linux主要的贡献者名单。
REPORTING-BUGS ---- Bug上报的指南。Documentation, README ---- 帮助、说明文档。
【文章福利】需要C/C++ Linux服务器架构师学习资料加群812855908(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等)
Linux内核体系结构简析简析
图1 Linux系统层次结构
最上面是用户(或应用程序)空间。这是用户应用程序执行的地方。用户空间之下是内核空间,Linux 内核正是位于这里。GNU C Library (glibc)也在这里。它提供了连接内核的系统调用接口,还提供了在用户空间应用程序和内核之间进行转换的机制。这点非常重要,因为内核和用户空间的应用程序使用的是不同的保护地址空间。每个用户空间的进程都使用自己的虚拟地址空间,而内核则占用单独的地址空间。
Linux 内核可以进一步划分成 3 层。最上面是系统调用接口,它实现了一些基本的功能,例如 read 和 write。系统调用接口之下是内核代码,可以更精确地定义为独立于体系结构的内核代码。这些代码是 Linux 所支持的所有处理器体系结构所通用的。在这些代码之下是依赖于体系结构的代码,构成了通常称为 BSP(Board Support Package)的部分。这些代码用作给定体系结构的处理器和特定于平台的代码。
Linux 内核实现了很多重要的体系结构属性。在或高或低的层次上,内核被划分为多个子系统。Linux 也可以看作是一个整体,因为它会将所有这些基本服务都集成到内核中。这与微内核的体系结构不同,后者会提供一些基本的服务,例如通信、I/O、内存和进程管理,更具体的服务都是插入到微内核层中的。每种内核都有自己的优点,不过这里并不对此进行讨论。
随着时间的流逝,Linux 内核在内存和 CPU 使用方面具有较高的效率,并且非常稳定。但是对于 Linux 来说,最为有趣的是在这种大小和复杂性的前提下,依然具有良好的可移植性。Linux 编译后可在大量处理器和具有不同体系结构约束和需求的平台上运行。一个例子是 Linux 可以在一个具有内存管理单元(MMU)的处理器上运行,也可以在那些不提供 MMU 的处理器上运行。
Linux 内核的 uClinux 移植提供了对非 MMU 的支持。
图2是Linux内核的体系结构
图2 Linux内核体系结构
Linux内核的主要组件有:系统调用接口、进程管理、内存管理、虚拟文件系统、网络堆栈、设备驱动程序、硬件架构的相关代码。
(1)系统调用接口
SCI 层提供了某些机制执行从用户空间到内核的函数调用。正如前面讨论的一样,这个接口依赖于体系结构,甚至在相同的处理器家族内也是如此。SCI 实际上是一个非常有用的函数调用多路复用和多路分解服务。在 ./linux/kernel 中您可以找到 SCI 的实现,并在 ./linux/arch 中找到依赖于体系结构的部分。(2)进程管理
进程管理的重点是进程的执行。在内核中,这些进程称为线程,代表了单独的处理器虚拟化(线程代码、数据、堆栈和 CPU 寄存器)。在用户空间,通常使用进程 这个术语,不过 Linux 实现并没有区分这两个概念(进程和线程)。内核通过 SCI 提供了一个应用程序编程接口(API)来创建一个新进程(fork、exec 或 Portable Operating System Interface [POSIX] 函数),停止进程(kill、exit),并在它们之间进行通信和同步(signal 或者 POSIX 机制)。进程管理还包括处理活动进程之间共享 CPU 的需求。内核实现了一种新型的调度算法,不管有多少个线程在竞争 CPU,这种算法都可以在固定时间内进行操作。这种算法就称为 O(1) 调度程序,这个名字就表示它调度多个线程所使用的时间和调度一个线程所使用的时间是相同的。O(1) 调度程序也可以支持多处理器(称为对称多处理器或 SMP)。您可以在 ./linux/kernel 中找到进程管理的源代码,在 ./linux/arch 中可以找到依赖于体系结构的源代码。
(3)内存管理
内核所管理的另外一个重要资源是内存。为了提高效率,如果由硬件管理虚拟内存,内存是按照所谓的内存页 方式进行管理的(对于大部分体系结构来说都是 4KB)。Linux 包括了管理可用内存的方式,以及物理和虚拟映射所使用的硬件机制。不过内存管理要管理的可不止 4KB 缓冲区。Linux 提供了对 4KB 缓冲区的抽象,例如 slab 分配器。这种内存管理模式使用 4KB 缓冲区为基数,然后从中分配结构,并跟踪内存页使用情况,比如哪些内存页是满的,哪些页面没有完全使用,哪些页面为空。这样就允许该模式根据系统需要来动态调整内存使用。为了支持多个用户使用内存,有时会出现可用内存被消耗光的情况。由于这个原因,页面可以移出内存并放入磁盘中。这个过程称为交换,因为页面会被从内存交换到硬盘上。内存管理的源代码可以在 ./linux/mm 中找到。(4)虚拟文件系统
虚拟文件系统(VFS)是 Linux 内核中非常有用的一个方面,因为它为文件系统提供了一个通用的接口抽象。VFS 在 SCI 和内核所支持的文件系统之间提供了一个交换层(请参看图4)。
图3 Linux文件系统层次结构
在 VFS 上面,是对诸如 open、close、read 和 write 之类的函数的一个通用 API 抽象。在 VFS 下面是文件系统抽象,它定义了上层函数的实现方式。它们是给定文件系统(超过 50 个)的插件。文件系统的源代码可以在 ./linux/fs 中找到。文件系统层之下是缓冲区缓存,它为文件系统层提供了一个通用函数集(与具体文件系统无关)。这个缓存层通过将数据保留一段时间(或者随即预先读取数据以便在需要是就可用)优化了对物理设备的访问。缓冲区缓存之下是设备驱动程序,它实现了特定物理设备的接口。
(5)网络堆栈
网络堆栈在设计上遵循模拟协议本身的分层体系结构。回想一下,Internet Protocol (IP) 是传输协议(通常称为传输控制协议或 TCP)下面的核心网络层协议。TCP 上面是 socket 层,它是通过 SCI 进行调用的。socket 层是网络子系统的标准 API,它为各种网络协议提供了一个用户接口。从原始帧访问到 IP 协议数据单元(PDU),再到 TCP 和 User Datagram Protocol (UDP),socket 层提供了一种标准化的方法来管理连接,并在各个终点之间移动数据。内核中网络源代码可以在 ./linux/net 中找到。(6)设备驱动程序
Linux 内核中有大量代码都在设备驱动程序中,它们能够运转特定的硬件设备。Linux 源码树提供了一个驱动程序子目录,这个目录又进一步划分为各种支持设备,例如 Bluetooth、I2C、serial 等。设备驱动程序的代码可以在 ./linux/drivers 中找到。(7)依赖体系结构的代码
尽管 Linux 很大程度上独立于所运行的体系结构,但是有些元素则必须考虑体系结构才能正常操作并实现更高效率。./linux/arch 子目录定义了内核源代码中依赖于体系结构的部分,其中包含了各种特定于体系结构的子目录(共同组成了 BSP)。对于一个典型的桌面系统来说,使用的是 x86 目录。每个体系结构子目录都包含了很多其他子目录,每个子目录都关注内核中的一个特定方面,例如引导、内核、内存管理等。这些依赖体系结构的代码可以在 ./linux/arch 中找到。如果 Linux 内核的可移植性和效率还不够好,Linux 还提供了其他一些特性,它们无法划分到上面的分类中。作为一个生产操作系统和开源软件,Linux 是测试新协议及其增强的良好平台。Linux 支持大量网络协议,包括典型的 TCP/IP,以及高速网络的扩展(大于 1 Gigabit Ethernet [GbE] 和 10 GbE)。Linux 也可以支持诸如流控制传输协议(SCTP)之类的协议,它提供了很多比 TCP 更高级的特性(是传输层协议的接替者)。
Linux 还是一个动态内核,支持动态添加或删除软件组件。被称为动态可加载内核模块,它们可以在引导时根据需要(当前特定设备需要这个模块)或在任何时候由用户插入。
Linux 最新的一个增强是可以用作其他操作系统的操作系统(称为系统管理程序)。最近,对内核进行了修改,称为基于内核的虚拟机(KVM)。这个修改为用户空间启用了一个新的接口,它可以允许其他操作系统在启用了 KVM 的内核之上运行。除了运行 Linux 的其他实例之外, Microsoft Windows也可以进行虚拟化。惟一的限制是底层处理器必须支持新的虚拟化指令。
Linux体系结构和内核结构区别
1.当被问到Linux体系结构(就是Linux系统是怎么构成的)时,我们可以参照下图这么回答:从大的方面讲,Linux体系结构可以分为两块:
(1)用户空间:用户空间中又包含了,用户的应用程序,C库
(2)内核空间:内核空间包括,系统调用,内核,以及与平台架构相关的代码
2.Linux体系结构要分成用户空间和内核空间的原因:
1)现代CPU通常都实现了不同的工作模式,
以ARM为例:ARM实现了7种工作模式,不同模式下CPU可以执行的指令或者访问的寄存器不同:
(1)用户模式 usr
(2)系统模式 sys
(3)管理模式 svc
(4)快速中断 fiq
(5)外部中断 irq
(6)数据访问终止 abt
(7)未定义指令异常
以(2)X86为例:X86实现了4个不同级别的权限,Ring0—Ring3 ;Ring0下可以执行特权指令,可以访问IO设备;Ring3则有很多的限制
2)所以,Linux从CPU的角度出发,为了保护内核的安全,把系统分成了2部分;
3.用户空间和内核空间是程序执行的两种不同状态,我们可以通过“系统调用”和“硬件中断“来完成用户空间到内核空间的转移
4.Linux的内核结构(注意区分LInux体系结构和Linux内核结构)
Linux驱动的platform机制
Linux的这种platform driver机制和传统的device_driver机制相比,一个十分明显的优势在于platform机制将本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源时通过platform_device提供的标准接口进行申请并使用。这样提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性。下面是SPI驱动层次示意图,Linux中的SPI总线可理解为SPI控制器引出的总线:
和传统的驱动一样,platform机制也分为三个步骤:
1、总线注册阶段:
内核启动初始化时的main.c文件中的kernel_init()→do_basic_setup()→driver_init()→platform_bus_init()→bus_register(&platform_bus_type),注册了一条platform总线(虚拟总线,platform_bus)。2、添加设备阶段:
设备注册的时候Platform_device_register()→platform_device_add()→(pdev→dev.bus = &platform_bus_type)→device_add(),就这样把设备给挂到虚拟的总线上。3、驱动注册阶段:
Platform_driver_register()→driver_register()→bus_add_driver()→driver_attach()→bus_for_each_dev(), 对在每个挂在虚拟的platform bus的设备作__driver_attach()→driver_probe_device(),判断drv→bus→match()是否执行成功,此时通过指针执行platform_match→strncmp(pdev→name , drv→name , BUS_ID_SIZE),如果相符就调用really_probe(实际就是执行相应设备的platform_driver→probe(platform_device)。)开始真正的探测,如果probe成功,则绑定设备到该驱动。从上面可以看出,platform机制最后还是调用了bus_register() , device_add() , driver_register()这三个关键的函数。
下面看几个结构体:
struct platform_device (/include/linux/Platform_device.h) { const char * name; int id; struct device dev; u32 num_resources; struct resource * resource; };
Platform_device结构体描述了一个platform结构的设备,在其中包含了一般设备的结构体struct device dev;设备的资源结构体struct resource * resource;还有设备的名字const char * name。(注意,这个名字一定要和后面platform_driver.driver àname相同,原因会在后面说明。)
该结构体中最重要的就是resource结构,这也是之所以引入platform机制的原因。
struct resource ( /include/linux/ioport.h) { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; struct resource *parent, *sibling, *child; };
其中 flags位表示该资源的类型,start和end分别表示该资源的起始地址和结束地址(/include/linux/Platform_device.h):
struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); void (*shutdown)(struct platform_device *); int (*suspend)(struct platform_device *, pm_message_t state); int (*suspend_late)(struct platform_device *, pm_message_t state); int (*resume_early)(struct platform_device *); int (*resume)(struct platform_device *); struct device_driver driver; };
Platform_driver结构体描述了一个platform结构的驱动。其中除了一些函数指针外,还有一个一般驱动的device_driver结构。
名字要一致的原因:上面说的驱动在注册的时候会调用函数bus_for_each_dev(), 对在每个挂在虚拟的platform bus的设备作__driver_attach()→driver_probe_device(),在此函数中会对dev和drv做初步的匹配,调用的是drv->bus->match所指向的函数。platform_driver_register函数中drv->driver.bus = &platform_bus_type,所以drv->bus->match就为platform_bus_type→match,为platform_match函数,该函数如下:
static int platform_match(struct device * dev, struct device_driver * drv) { struct platform_device *pdev = container_of(dev, struct platform_device, dev); return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); }
是比较dev和drv的name,相同则会进入really_probe()函数,从而进入自己写的probe函数做进一步的匹配。所以dev→name和driver→drv→name在初始化时一定要填一样的。
不同类型的驱动,其match函数是不一样的,这个platform的驱动,比较的是dev和drv的名字,还记得usb类驱动里的match吗?它比较的是Product ID和Vendor ID。
个人总结Platform机制的好处:
1、提供platform_bus_type类型的总线,把那些不是总线型的soc设备都添加到这条虚拟总线上。使得,总线——设备——驱动的模式可以得到普及。
2、提供platform_device和platform_driver类型的数据结构,将传统的device和driver数据结构嵌入其中,并且加入resource成员,以便于和Open Firmware这种动态传递设备资源的新型bootloader和kernel 接轨。
Linux内核体系结构
因为Linux内核是单片的,所以它比其他类型的内核占用空间最大,复杂度也最高。这是一个设计特性,在Linux早期引起了相当多的争论,并且仍然带有一些与单内核固有的相同的设计缺陷。
为了解决这些缺陷,Linux内核开发人员所做的一件事就是使内核模块可以在运行时加载和卸载,这意味着您可以动态地添加或删除内核的特性。这不仅可以向内核添加硬件功能,还可以包括运行服务器进程的模块,比如低级别虚拟化,但也可以替换整个内核,而不需要在某些情况下重启计算机。
想象一下,如果您可以升级到Windows服务包,而不需要重新启动……内核模块
如果Windows已经安装了所有可用的驱动程序,而您只需要打开所需的驱动程序怎么办?这本质上就是内核模块为Linux所做的。内核模块,也称为可加载内核模块(LKM),对于保持内核在不消耗所有可用内存的情况下与所有硬件一起工作是必不可少的。
模块通常向基本内核添加设备、文件系统和系统调用等功能。lkm的文件扩展名是.ko,通常存储在/lib/modules目录中。由于模块的特性,您可以通过在启动时使用menuconfig命令将模块设置为load或not load,或者通过编辑/boot/config文件,或者使用modprobe命令动态地加载和卸载模块,轻松定制内核。
第三方和封闭源码模块在一些发行版中是可用的,比如Ubuntu,默认情况下可能无法安装,因为这些模块的源代码是不可用的。该软件的开发人员(即nVidia、ATI等)不提供源代码,而是构建自己的模块并编译所需的.ko文件以便分发。虽然这些模块像beer一样是免费的,但它们不像speech那样是免费的,因此不包括在一些发行版中,因为维护人员认为它通过提供非免费软件“污染”了内核。
内核并不神奇,但对于任何正常运行的计算机来说,它都是必不可少的。Linux内核不同于OS X和Windows,因为它包含内核级别的驱动程序,并使许多东西“开箱即用”。希望您能对软件和硬件如何协同工作以及启动计算机所需的文件有更多的了解。
-
深入分析Linux内核源码完整版
2018-12-10 18:04:441.3走进Linux内核 1.3.1 Linux内核的特征 1.3.2 Linux内核版本的变化 1.4 分析Linux内核的意义 1.4.1 开发适合自己的操作系统 1.4.2 开发高水平软件 1.4.3 有助于计算机科学的教学和科研 1.5 Linux内核... -
深入剖析Linux内核与设备驱动 完整版 pdf
2017-04-25 09:50:52深入剖析Linux内核与设备驱动 完整版 pdf -
《Linux内核精髓:精通Linux内核必会的75个绝技》迷你书
2013-02-17 10:45:43鉴于此,《Linux内核精髓:精通Linux内核必会的75个绝技》选取了资源管理(CPU、内存、进程等)、文件系统、网络、虚拟化、省电、调试、概要分析、追踪、内核调整等Linux内核的核心主题进行了深入剖析和讲解,总结出... -
CentOS下编译Linux内核
2022-03-23 15:14:36编译内核是一项很简单的事情,但却是进入Linux内核世界的第一步,想要开发内核代码,想要了解内核的运行机制,第一步就是编译Linux内核,以下是在centos7.5环境下编译内核的具体流程。 1、下载内核 内核的源码的...前言
编译内核是一项很简单的事情,但却是进入Linux内核世界的第一步,想要开发内核代码,想要了解内核的运行机制,第一步就是编译Linux内核,以下是在centos7.5环境下编译内核的具体流程。
1、下载内核
内核的源码的官方网站为The Linux Kernel Archives,在此网站下载最新内核源码。
2、解压内核源码
[root@rt7_node03 src]# tar xvf linux-5.16.14.tar.xz -C /usr/src/ [root@rt7_node03 src]# ln -sv linux-5.16.14 linux 'linux' -> 'linux-5.16.14' [root@rt7_node03 tmp]# cd /usr/src/ [root@rt7_node03 src]# ls debug kernels linux linux-5.16.14
3、配置依赖的环境
- 确保根分区可用空间在15G以上(扩容根分区可参考Linux “/“ 分区扩容_巭犇的博客-CSDN博客)
- 确保gcc版本在5.0以上(升级gcc可参考CentOS下快速升级gcc版本_巭犇的博客-CSDN博客)
- 安装依赖的软件包。
[root@rt7_node03 linux]# yum groupinstall Development Tools [root@rt7_node03 linux]# yum install ncurses-devel [root@rt7_node03 linux]# yum install elfutils-libelf-devel-0.176-5.el7.x86_64 [root@rt7_node03 linux]# yum install openssl-devel [root@rt7_node03 linux]# yum install bc-1.06.95-13.el7.x86_64
在进行编译的时候提供依赖的文件,我当前的环境是系统版本为CentOS7.5,为最小化安装,实际情况根据编译的时候提示缺少了哪些文件,安装相应的软件包即可。
4、进入源码目录,使用make menuconfig开启菜单选项,手动选择内核功能
[root@rt7_node03 linux]# make menuconfig UPD scripts/kconfig/mconf-cfg HOSTCC scripts/kconfig/mconf.o HOSTCC scripts/kconfig/lxdialog/checklist.o HOSTCC scripts/kconfig/lxdialog/inputbox.o HOSTCC scripts/kconfig/lxdialog/menubox.o HOSTCC scripts/kconfig/lxdialog/textbox.o HOSTCC scripts/kconfig/lxdialog/util.o HOSTCC scripts/kconfig/lxdialog/yesno.o HOSTCC scripts/kconfig/confdata.o HOSTCC scripts/kconfig/expr.o LEX scripts/kconfig/lexer.lex.c YACC scripts/kconfig/parser.tab.[ch] HOSTCC scripts/kconfig/lexer.lex.o HOSTCC scripts/kconfig/menu.o HOSTCC scripts/kconfig/parser.tab.o HOSTCC scripts/kconfig/preprocess.o HOSTCC scripts/kconfig/symbol.o HOSTCC scripts/kconfig/util.o HOSTLD scripts/kconfig/mconf
配置完成后会生成.config的隐藏文件,如果不知道该开启哪些功能也可以直接选用当前系统的配置文件,这里直接使用当前系统的配置文件。
[root@rt7_node03 linux]# cp /boot/config-3.10.0-514.el7.x86_64 ./.config
5、编译内核
[root@rt7_node03 linux]# make -j 8 # "-j 8" 代表使用8颗cpu同事编译,这里可根据实际情况而定 /usr/src/linux-5.16.14/Makefile:661: include/config/auto.conf: No such file or directory /usr/src/linux-5.16.14/Makefile:709: include/config/auto.conf.cmd: No such file or directory SYNC include/config/auto.conf.cmd HOSTCC scripts/kconfig/conf.o HOSTLD scripts/kconfig/conf ...
此步骤会对.config文件中的每一个选项再次确认,全部确认即可(我这里是8颗cpu同时在编译大概需要二十多分钟,如果cpu少的话,时间会更久一些)
6、安装模块
[root@rt7_node03 linux]# make modules_install ... SIGN /lib/modules/5.16.14/kernel/sound/usb/misc/snd-ua101.ko INSTALL /lib/modules/5.16.14/kernel/sound/usb/snd-usb-audio.ko SIGN /lib/modules/5.16.14/kernel/sound/usb/snd-usb-audio.ko INSTALL /lib/modules/5.16.14/kernel/sound/usb/snd-usbmidi-lib.ko SIGN /lib/modules/5.16.14/kernel/sound/usb/snd-usbmidi-lib.ko INSTALL /lib/modules/5.16.14/kernel/sound/usb/usx2y/snd-usb-us122l.ko SIGN /lib/modules/5.16.14/kernel/sound/usb/usx2y/snd-usb-us122l.ko INSTALL /lib/modules/5.16.14/kernel/sound/usb/usx2y/snd-usb-usx2y.ko SIGN /lib/modules/5.16.14/kernel/sound/usb/usx2y/snd-usb-usx2y.ko INSTALL /lib/modules/5.16.14/kernel/virt/lib/irqbypass.ko SIGN /lib/modules/5.16.14/kernel/virt/lib/irqbypass.ko DEPMOD /lib/modules/5.16.14
安装完成后在/lib/modules/目录下会生成一个同内核版本号的目录,目录下便是新内核的模块。
7、安装内核
[root@rt7_node03 linux]# make install sh ./arch/x86/boot/install.sh 5.16.14 \ arch/x86/boot/bzImage System.map "/boot" [root@rt7_node03 linux]#
安装完后会在/boot目录下生成新的内核文件。
[root@rt7_node03 linux]# ll /boot/ total 187028 lrwxrwxrwx 1 root root 24 Mar 23 16:32 System.map -> /boot/System.map-5.16.14 -rw-------. 1 root root 3113253 Nov 23 2016 System.map-3.10.0-514.el7.x86_64 -rw-r--r-- 1 root root 4659281 Mar 23 16:32 System.map-5.16.14 -rw-r--r-- 1 root root 4659281 Mar 23 16:25 System.map-5.16.14.old -rw-r--r--. 1 root root 137696 Nov 23 2016 config-3.10.0-514.el7.x86_64 drwxr-xr-x. 2 root root 27 Nov 7 2018 grub drwx------. 6 root root 111 Mar 23 16:34 grub2 -rw-------. 1 root root 48321021 Nov 7 2018 initramfs-0-rescue-33c42a62363749ea9b8fa6116acbeb3e.img -rw-------. 1 root root 20732112 Nov 7 2018 initramfs-3.10.0-514.el7.x86_64.img -rw-------. 1 root root 18546695 Nov 7 2018 initramfs-3.10.0-514.el7.x86_64kdump.img -rw------- 1 root root 62203659 Mar 23 16:34 initramfs-5.16.14.img -rw-r--r--. 1 root root 613751 Nov 7 2018 initrd-plymouth.img -rw-r--r--. 1 root root 277953 Nov 23 2016 symvers-3.10.0-514.el7.x86_64.gz lrwxrwxrwx 1 root root 21 Mar 23 16:32 vmlinuz -> /boot/vmlinuz-5.16.14 -rwxr-xr-x. 1 root root 5392080 Nov 7 2018 vmlinuz-0-rescue-33c42a62363749ea9b8fa6116acbeb3e -rwxr-xr-x. 1 root root 5392080 Nov 23 2016 vmlinuz-3.10.0-514.el7.x86_64 -rw-r--r-- 1 root root 8720224 Mar 23 16:32 vmlinuz-5.16.14 -rw-r--r-- 1 root root 8720224 Mar 23 16:25 vmlinuz-5.16.14.old
新内核会自动写入到引导文件中,直接重启系统,在选择内核的界面选中新的内核即可。
[root@rt7_node03 linux]# cat /boot/grub2/grub.cfg ... ### BEGIN /etc/grub.d/10_linux ### menuentry 'CentOS Linux (5.16.14) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-514.el7.x86_64-advanced-bc95c848-a340-412c-92f1-09f6a8ed94ec' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod xfs set root='hd0,msdos1' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint='hd0,msdos1' f0b3417a-c9b1-4d04-9c2a-77ea4a0abb96 else search --no-floppy --fs-uuid --set=root f0b3417a-c9b1-4d04-9c2a-77ea4a0abb96 fi linux16 /vmlinuz-5.16.14 root=/dev/mapper/cl-root ro biosdevname=0 net.ifnames=0 console=ttyS0,115200n8 LANG=en_US.UTF-8 initrd16 /initramfs-5.16.14.img } ...
7、验证新内核版本。
[root@rt7_node03 linux]# uname -a Linux rt7_node03 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux [root@rt7_node03 linux]# uname -a Linux rt7_node03 5.16.14 #1 SMP PREEMPT Wed Mar 23 15:56:47 CST 2022 x86_64 x86_64 x86_64 GNU/Linux
内核已升到5.16.14
总结
这个实验只是体验了内核编译的过程,并未修改内核的源码,后续将对内核源码进行解读,并插入自己的内核代码,将自己的内核代码运行在操作系统中。
-
Linux内核开发_1_编译LInux内核
2020-05-13 01:23:32Linux内核版本: cat /proc/version Linux version 4.15.0-20-generic (buildd@lgw01-amd64-039)\ (gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3)) #21-Ubuntu SMP Tue Apr 24 06:16:15 UTC 2018 ... -
Linux内核设计与实现(第三版中文高清带目录)高清完整PDF版
2014-06-13 15:27:04Linux内核设计与实现(第三版中文高清带目录).pdf 对内核学习的同学们很有帮助 -
深度:一文看懂Linux内核!Linux内核架构和工作原理详解
2020-02-27 22:59:45Linux内核就是基于这个策略实现的。Linux进程1.采用层次结构,每个进程都依赖于一个父进程。内核启动init程序作为第一个进程。该进程负责进一步的系统初始化操作。init进程是进程树的根,所有的进程都直接或者间接... -
Linux内核移植入门
2021-11-20 23:50:27修改配置文件内核编译编译结果:几种linux内核文件的区别开发板上U-Boot启动linux内核内核Kconfig语法使用1.make menuconfig 是如何找到 Kconfig?2.Makefile 要编译一个 .o 文件是如何在Kconfig中配置的?添加驱动到... -
安卓与linux内核版本的关系,Linux内核是如何定义版本的?
2021-05-11 03:38:33我们平时常用到的Linux系统包括CentOS、Ubuntu等,其实这些都是Linux的发行版本,Linux还有...截止到2021年4月24日,最新稳定版本是5.11.16Linux内核版本大致可以分为以下几类:mainline:主线版本。stable:稳定版... -
linux内核源码分析系列文章汇总
2022-04-09 11:05:02七、内存专题 1、linux内核源码分析之内存概述 2、linux内核源码分析之内存 3、linux内核源码分析之虚拟内存映射 4、linux内核源码分析之物理内存组织结构 5、linux内核源码分析之伙伴系统(一) 6、linux内核源码... -
Linux 内核和 Windows 内核有什么区别?
2021-02-20 09:46:29对于服务器使用的操作系统基本上都是 Linux,而且内核源码也是开源的,任何人都可以下载,并增加自己的改动或功能,Linux 最大的魅力在于,全世界有非常多的技术大佬为它贡献代码。 这两个操作系统各有千秋,不分... -
linux内核版本介绍
2021-01-29 16:13:32Linux内核版本号由3组数字组成:第一个组数字.第二组数字.第三组数字 第一个组数字:目前发布的内核主版本。 第二个组数字:偶数表示稳定版本;奇数表示开发中版本。 第三个组数字:错误修补的次数。 可以使 -
使用VSCode进行linux内核代码阅读和开发
2021-06-14 19:18:40使用VSCode进行linux内核代码阅读和开发现状新的方法安装与配置1.安装VSCode2.安装Remote - SSH插件3.添加远程主机4.安装clangd5.在远程服务器安装bear6.配置clangd7.触发clangd工作效果遇到的问题总结参考链接 现状... -
Linux内核源代码情景分析 (上下册 高清非扫描 )
2011-03-27 21:27:03丛书名: Linux内核源代码情景分析 出版社:浙江大学出版社 目录 第1章 预备知识 1.1 Linux内核简介. 1.2 Intel X86 CPU系列的寻址方式 1.3 i386的页式内存管理机制 1.4 Linux内核源代码中的C语言代码 1.5 Linux... -
深入理解linux内核中文第三版(带目录)
2014-03-09 17:52:33这个是真正的第三版,网上的小文件基本上都是第一版。之前上传了英文版第三版,可以对照着看。 -
认识linux内核结构
2022-03-22 10:28:49linux内核结构 用户级 函数库 :提供了应用程序支配内核干活的接口 内核级 Linux内核主要由五个子系统组成:进程调度,内存管理,虚拟文件系统,网络接口,进程间通信。 1.进程调度(Process Scheduler):控制多个... -
查看linux内核的三种方法介绍
2022-04-12 17:54:44当您需要了解系统上正在使用的确切Linux内核版本时,您可能会遇到这种情况。借助功能强大的Linux 行,您可以轻松地找到答案。 在本文中,我将向您展示各种了解内核版本以及这些数字实际含义的方法。 如何找到... -
【linux kernel】记一次linux内核裁剪总结
2022-03-20 13:35:03记一次linux内核裁剪总结 一、背景 在linux内核中,小生构建了一个大约5.7M大小的linux内核zImage镜像。目的:想着将其裁剪和缩小,于是乎开始了裁剪linux内核之路。 本篇文章记录一下关于fs项是如何配置和... -
Linux编译并更新内核(替换Linux内核)
2021-07-01 17:31:10Linux编译并更新内核(替换Linux内核) 实验环境: OS: Ubuntu20.10LTS Old Kernel: linux 5.8.0 New Kernel: linux 5.13.0 1、获取Linux Kernel源码 可以通过官网下载原始版本的内核代码,也可以使用其它厂商或自己... -
Linux内核的参数优化(尽量详细的总结)
2022-03-30 21:52:06Linux内核有非常多的参数,而对这些内核参数的修改会尽可能的提高内核的稳定性,并且,在业务高峰期的时候,可以保证内核尽可能的稳定高效,而不是某些非常低级的DDOS洪水就崩溃的Linux内核。总的来说,系统内核的... -
【Linux 内核】Linux 内核体系架构 ( 进程调度 | 内存管理 | 中断管理 | 设备管理 | 文件系统 )
2022-03-21 23:43:21四、设备管理 Linux 内核 支持的外设类型 是最多的 , 设备树 PCI 总线设备 设备模型 Kobject ACPI 网络设备驱动 块设备驱动 字符设备驱动 设备管理 位于 下图 Linux 内核整体架构图 中的 内核空间 ; 五、文件系统 ...