热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Linux内核学习笔记(11):内核配置和编译原理

Linux-内核-学习笔记(11):内核配置和编译原理



Linux-内核-学习笔记(11):内核配置和编译原理


一、内核简介


1. 操作系统


1.1、什么是操作系统?

操作系统本质上是一个程序,由很多个源文件构成,需要编译连接成操作系统程序。它主要作用就是管理计算机硬件,给应用程序提供一个运行环境。例如linux、windows、android、ucos就是操作系统。

1.2、操作系统核心功能

操作系统就相当于你的一个管家,是一些功能的综合体,他会管理下面这些内容,帮助用户解决一些复杂的分配和调用问题。


  • 内存管理:如果没有操作系统,内存是需要程序自己来管理的。譬如在uboot中要使用内存时是自己随便用的,自己定义内存的位置和大小,没有注册也没有限制。这时候如果程序自己不小心把同一块内存重复用了就会出现程序逻辑错误(覆盖)。随着系统变大了之后(内存多了),内存管理会非常麻烦。但是有了操作系统之后,操作系统负责管控所有的内存,所有的应用程序需要使用内存时都要向操作系统去申请和注册,由操作系统的内存管理模块来分配内存给你使用,这样好处是可以保证内存使用不会冲突。

  • 进程调度:操作系统下支持多个应用程序同时运行(所以可以一边聊QQ一边看电影···),这是宏观上的并行。实际上在单核心CPU上微观上是不能并行的,宏观上的并行就是操作系统提供的分时复用机制,也就是某个时间切换到一个进程下执行,执行完成后再切换到另外一个进程。操作系统的进程调度模块负责在各个进程之间进行切换

  • 硬件设备管理:没有操作系统时要控制任何硬件都要自己写代码,有了操作系统后操作系统本身会去控制各个硬件,应用程序就不用考虑硬件的具体细节了。操作系统的硬件设备管理模块就是驱动模块

  • 文件系统:文件系统是管理存储设备的一种方式。存储设备是由很多个扇区组成的,每个扇区有512/1024/2048/4096(各种)字节,存储设备要以扇区为单位进行读写。如果没有文件系统,程序要自己去读写扇区,就得记得哪个文件在哪个扇区。有了文件系统之后用户不用再关注扇区,只用关注文件系统中的目录和文件名,而不用管这个文件在物理磁盘的哪个扇区。

同时,操作系统还有一些扩展功能:(1)协议栈。(2)有用的应用程序包。应用程序本身不属于操作系统内核的一部分,应用程序是给人用的,面向某种功能的。譬如ping程序用来测试网络是否联通,ifconfig程序用来配置网卡。

1.3、内核和发行版区别

区别1:

内核是操作系统内核的简称内核负责实现操作系统的核心功能(资源管理模块,譬如内存管理、调度系统······),内核不包括应用程序。所以说只有内核用户是没法用的(就像只有windows系统一样),因为人做任何事情都是通过相应的应用程序来完成的(需要给windows装软件)。所以卖操作系统的人把内核和一些常用的应用程序打包在一起提供给普通用户,这就是操作系统的发行版(也就是普通意义上的操作系统)。所以 发行版包含内核和应用程序

区别2:

内核只有一个,只是版本不同。下载linux内核链接。

发行版有很多。譬如ubuntu、redhat、suse、centos······都是使用一个内核做出来的,只是应用程序不同。

二、内核的框架

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

在了解内核时,首先要知道上述这种分层结构:应用层、操作系统层和硬件层。三者之间由于任务不同,主要操作的对象不同,实现了各层的着重点不同,但是三者之间又紧密联系着。层次之间实现下层被上层所调用,即硬件被OS所调用,而OS是给APP用来使用的。

操作系统管理着硬件层,它将硬件抽象成一个个的API,应用层在想要控制某个硬件设备时,通过操作系统层的API对硬件设备进行调用和控制,从而完成三个层次之间的协调配合。

1. 内核和驱动的关联

(1)驱动其实属于内核的一部分。驱动就是内核中的硬件设备管理模块

(2)在内核态运行是管理员权限,而在用户态则是用户权限,是有一部分限制的。驱动工作在内核态。这里将工作状态划分的目的主要是为了在内核态时运行一些重要的程序,使其不受权限的束缚。所以驱动程序故障可能导致整个内核崩溃,驱动程序漏洞会使内核不安全。

2. 内核和应用程序的关联

(1)应用程序不属于内核,而是在内核之上的。

(2)应用程序工作在用户态,是受限制的。每一个应用程序就是一个进程,系统在工作时有许多个应用程序和一个内核,但是同一时间CPU只能服务一个。应用程序如果想得到内存需要向CPU去申请(malloc和free),内核的目的是服务应用程序,所以应用程序才是最终要实现的目标(重点是要生成能工作的APP),而操作系统只是一个手段(windows系统只是用来工作的)。

(3)应用程序故障不会导致内核崩溃,并且不会影响到其他的进程。因为它们是相互独立的进程,你的区域坏了不会影响我的区域。

(4)应用程序通过内核定义的API接口来调用内核工作。应用层执行应用需要调用硬件,所以需要通过内核来调用驱动从而操作硬件执行相应的动作,也可以理解为内核就是为应用程序提供底层资源管理的服务员

3. 内核和根文件系统的关联

(1)根文件系统提供根目录。整个文件系统是一个树形的。从根目录出发的方式就是绝对路径,相对路径的原理也是通过转成绝对路径去找的。反斜杠“/”就是根目录,也就是最起始的目录。我们常说的挂载mount就是一个连接点,如果说将XX挂载到XX,就是将这个东西的位置指定到某个特定的路径下。

(2)进程1存放在根文件系统中,是用户态和内核态的一个交界处。是整个系统中的第一个应用程序。

(2)内核启动最后会去装载根文件系统。刚开始内核启动时没有目录的,整个操作系统的根目录就是从根文件系统中来的。因此根文件系统为操作系统启动提供了很多必备的资源:根目录和进程1

4. linux内核的模块化设计

因为linux内核很庞大,代码量很大、东西很多,如果设计时完全设计成一体(各个文件、各个函数之间紧耦合),复杂度超出了人所能理解的范围。所以模块化设计也是一种必要。模块化设计就是内核中各个功能模块在代码上是彼此独立的,譬如说调度系统和内存管理系统之间并没有全局变量的互相引用,甚至函数互相调用也很少,就算有也是遵循一个接口规范的。模块化设计的目的就是实现功能模块的松耦合

配置时可裁剪。linux内核在编译之前可以进行配置,配置时可以选择将组成内核的成千上万个模块每一个要或者不要。要了之后还有更多的一些细节的配置。

模块化编译和安装。为了操作方便,逐渐从静态的升级变成了动态的升级(不需要重启系统,更不需要重新烧录系统)。这种动态的升级也是由模块化来支持的。

源码中使用条件编译。这种在uboot中已经见过了。通过宏开关来控制编译时候哪个编译哪个不编译,从而影响究竟使用了哪个模块。

这种模块化设计的优点是:(1)功能可裁剪、灵活性;(2)可扩展性(动态安装卸载、新硬件支持);(3)利于协作。

三、内核配置和编译原理


1. 内核源码目录分析

在分析内核源码目录之前,首先要将内核目录解压开,并将kernel目录打包一份发送到windows端方便查看:

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

接近着分析kernel内核源码目录树的各个目录代表的意思:

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

(1)arch:arch是architecture的缩写,意思是架构。arch目录下是好多个不同架构的CPU的子目录,譬如arm这种cpu的所有文件都在arch/arm目录下,X86的CPU的所有文件都在arch/x86目录下。

(2)block:英文是块的意思,在linux中block表示块设备(以块(多个字节组成的整体,类似于扇区)为单位来整体访问),譬如说SD卡、iNand、Nand、硬盘等都是块设备。你几乎可以认为块设备就是存储设备。block目录下放的是一些linux存储体系中关于块设备管理的代码。

(3)crypto:英文意思是加密。这个目录下放了一些各种常见的加密算法的C语言代码实现。譬如crc32、md5、sha1等。

(4)Documentation:里面放了一些文档。

(5)drivers:驱动目录,里面分门别类的列出了linux内核支持的所有硬件设备的驱动源代码。

(6)firmware:固件。固件其实是软件,不过这个软件是固话到IC里面运行的叫固件。就像S5PV210里的iROM代码。

(7)fs:fs就是file system,文件系统,里面列出了linux支持的各种文件系统的实现。

(8)include:头文件目录,公共的(各种CPU架构共用的)头文件都在这里。每种CPU架构特有的一些头文件在arch/arm/include目录及其子目录下。

(9)init:init是初始化的意思,这个目录下的代码就是linux内核启动时初始化内核的代码。

(10)ipc:ipc就是inter process commuication,进程间通信,里面都是linux支持的IPC的代码实现。

(11)kernel:kernel就是内核,就是linux内核,所以这个文件夹下放的就是内核本身需要的一些代码文件。

(12)lib:lib是库的意思,这里面都是一些公用的有用的库函数,注意这里的库函数和C语言的库函数不一样的。在内核编程中是不能用C语言标准库函数,这里的lib目录下的库函数就是用来替代那些标准库函数的。譬如在内核中要把字符串转成数字用atoi,但是内核编程中只能用lib目录下的atoi函数,不能用标准C语言库中的atoi。譬如在内核中要打印信息时不能用printf,而要用printk,这个printk就是我们这个lib目录下的。

(13)mm:mm是memory management,内存管理,linux的内存管理代码都在这里。

(14)net:该目录下是网络相关的代码,譬如TCP/IP协议栈等都在这里。

(15)scripts:脚本,这个目录下全部是脚本文件,这些脚本文件不是linux内核工作时使用的,而是用来辅助对linux内核进行配置编译生产的。

(16)security:安全相关的代码。不用去管。

(17)sound:音频处理相关的。

(18)tools:linux中用到的一些有用工具。

(19)usr:目录下是initramfs相关的,和linux内核的启动有关,暂时不用去管。

(20)virt:内核虚拟机相关的,暂时不用管。

(21)Kbuild:Kbuild是kernel build的意思,就是内核编译的意思。这个文件就是linux内核特有的内核编译体系需要用到的文件。

(22)Makefile:这个是linux内核的总makefile,整个内核工程用这个Makefile来管理的。

(23)mk:是九鼎在移植时自己添加的,不是linux内核本身的东西。九鼎添加这个文件的作用是用这个文件来整天管理kernel目录的配置和编译,也就是说这个文件有点类似于我们之前移植uboot时自己创建的那个cp.sh。

2. 内核配置第一步(make x210ii_qt_defconfig)


2.1、方法演示

在进行make之前,先要检查Makefile中的交叉编译工具是否正确,并确定ARCH=arm以保证编译时能找到arch/arm目录。

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

2.2、原理分析

配置第一步的主要目的是为了得到 .config文件。这个文件是一个隐藏文件,是linux内核在编译过程中很重要的一个文件,其作用类似与uboot中的include/configs/x210_sd.h,内核在编译过程中会读取.config中的配置项,并且用这些配置项去指导整个编译链接过程

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

.config文件的格式类似于脚本文件,其中的每一行都是一个配置项,这些配置项被配置的值最终用来决定内核编译时将哪些内容以什么方式来编译

从.config文件的规模可以看出linux内核的可配置项有两三千个。所以linux内核是高度可配置的,而且linux内核的所有配置项很难全部搞明白。因为linux内核的配置项太多太繁杂超出了人的大脑能够记忆和处理的数量级,因此linux内核不像uboot那样直接手工配置,而是发明了一个图形化的配置工具menuconfig

3. 内核配置第二步(make menuconfig)


3.1、方法演示

在make menuconfig之前,要确保ncurses安装。可以使用apt-get install libncurses5-dev

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

3.2、原理分析

配置第二步的主要目的是为了通过menuconfig来配置.config文件中的内容。.config中的大部分内容通过make x210ii_qt_defconfig进行了默认的配置,剩下一些细节的内容或者我们想要添加的配置内容都要通过make menuconfig进行添加。

make xxx_defconfig这一步其实是参考别人已经做好的,这样做有很多好处:减少很多工作量,避开了很多自己不懂的配置项(譬如对内存管理的、调度系统的等模块的配置项),我们只用管自己需要管的。因此make x210ii_qt_defconfig其实相当于:cp arch/arm/configs/x210ii_qt_defconfig .config,这两个其实是一个文件,只是复制出来。

make menuconfig其实就是读取第一步得到的.config,然后给我们一个图形化的界面,让我们可以更加容易的找到自己想要修改的配置项,然后更改配置他。

menuconfig方法详解见第四章:menuconfig原理及使用方法。


4. 内核编译(make)

当执行make时,即内核根据配置好的内容进行编译。我们通过make x210ii_qt_defconfig对.config文件进行了第一步的配置,也就是完成了大部分默认的配置工作,然后再利用make menuconfig对.config文件进行一些细微的更改,最终得到的一个完整的.config文件。这个.config文件中记录了我们设定的配置内容(指导内核编译什么不编译什么,以什么方式编译等),然后.config文件会根据内部的内容信息去影响Makefile文件,利用Makefile文件的条件判断来决定编译不编译哪些模块,最终影响启动后的内核。

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

四、menuconfig原理及使用方法


1. 原理分析

ncurses库是linux中用来实现文字式的图形界面,linux内核中使用了ncurses库来提供menuconfig。scripts\kconfig\lxdialog目录下的一些c文件就是用来提供menuconfig的那些程序源代码。

我们说过make menuconfig其实就是读取.config文件后并通过图像化方式展示给我们。,这个图形化界面中间的选择区中有很多个选择项,每个选择项对应.config文件中的一个配置项,每一个选择项都可以被选择和配置操作,选择区中的某些项还包含子目录的。选择区太短放不下所有的一个目录层级的选项,可以用箭头按键的向上箭头和向下箭头来上翻和下翻。

那menuconfig是如何显示菜单的目录结构呢?

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

是由内核源码树各个目录下的Kconfig文件来支持的。Kconfig文件中按照一定的格式包含了一个又一个的配置项,每一个配置项在make menuconfig中都会成为一个菜单项目。而且menuconfig中显示的菜单目录结构和源码目录中的Kconfig的目录结构是一样的。(如果在相应的Kconfig文件中删除一个config项,则再次make menuconfig时这个项目已经看不到了)

内核源码目录树中每一个Kconfig都会source引入其所有子目录下的Kconfig,从而保证了所有的Kconfig项目都被包含进menuconfig中。这个也告诉我们:如果你自己在linux内核中添加了一个文件夹,一定要在这个文件夹下创建一个Kconfig文件,然后在这个文件夹的上一层目录的Kconfig中source引入这个文件夹下的Kconfig文件。

通过menuconfig设置的配置方式保存到哪了呢?

menuconfig或者config后面空格隔开的大写字母表示的类似于 DM9000 的就是这个配置项的配置项名字,这个字符串前面添加CONFIG_后就构成了.config中的配置项名字。

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

刚才已经知道menuconfig的菜单内容来自于Kconfig文件,但是每一个菜单的选择结果(Y、N、M)却不是保存在Kconfig文件中的。Kconfig文件是不变的,Kconfig文件只是决定有没有这个菜单项,并不管这个菜单项的选择结果。

menuconfig工作时在我们make menuconfig打开时,他会读取.config文件,并且用.config文件中的配置选择结果来初始化menuconfig中各个菜单项的选择值。因此我们改变menuconfig的配置方式之后,会自动保存到.config文件中

总结:菜单项的项目内容从Kconfig文件来,菜单项的选择值从.config文件来

2. 使用方法

箭头按键导航整个菜单,回车按键选择子菜单(注意选项后面有 —>的选项才是有子菜单的,没有这个标识的没有子菜单),高亮的字母是热键(快捷键),键盘按键Y、N、M三个按键的作用分别是将选中模块编入、去除、模块化。双击ESC表示退出,按下?按键可以显示帮助信息,按下/按键可以输入搜索内容来全局搜索信息(类似于vi中的搜索),[]不可以模块化,<>的才可以模块化

inux内核中一个功能模块有三种编译方法:一种是编入、一种去去除、一种是模块化。所谓编入就是将这个模块的代码直接编译连接到zImage中去,去除就是将这个模块不编译链接到zImage中模块化是将这个模块仍然编译,但是不会将其链接到zImage中,会将这个模块单独链接成一个内核模块.ko文件,将来linux系统内核启动起来后可以动态的加载或卸载这个模块。

在menuconfig中选项前面的括号里,*表示编入,空白表示去除,M表示模块化

Linux-内核-学习笔记(11):内核配置和编译原理 - 文章图片

(1)tristate意思是三态(3种状态,对应Y、N、M三种选择方式),bool是要么真要么假(对应Y和N)。所以tristate的意思就是这个配置项可以被三种选择,bool的意思是这个配置项只能被2种选择。

(2)depends中文意思是“取决于”或者“依赖于”,所以depends在这里的意思是:本配置项依赖于另一个配置项。如果那个依赖的配置项为Y或者M,则本配置项才有意义;如果依赖的哪个配置项本身被设置为N,则本配置项根本没有意义。

depends并不要求依赖的配置项一定是一个,可以是多个,而且还可以有逻辑运算。这种时候只要依赖项目运算式子的裸机结果为真则依赖就成立。

(3)select表示当该配置被选中时,对应的哪些配置也会被选中。

(4)help 帮助信息,告诉我们这个配置项的含义,以及如何去配置他。



推荐阅读
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • 嵌入式处理器的架构与内核发展历程
    本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了win7系统休眠功能无法启动和关闭的解决方法,包括在控制面板中启用休眠功能、设置系统休眠的时间、通过命令行定时休眠、手动进入休眠状态等方法。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了2020年计算机二级MSOffice的选择习题及答案,详细解析了操作系统的五大功能模块,包括处理器管理、作业管理、存储器管理、设备管理和文件管理。同时,还解答了算法的有穷性的含义。 ... [详细]
  • CEPH LIO iSCSI Gateway及其使用参考文档
    本文介绍了CEPH LIO iSCSI Gateway以及使用该网关的参考文档,包括Ceph Block Device、CEPH ISCSI GATEWAY、USING AN ISCSI GATEWAY等。同时提供了多个参考链接,详细介绍了CEPH LIO iSCSI Gateway的配置和使用方法。 ... [详细]
author-avatar
shengxin11
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有