热门标签 | 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 帮助信息,告诉我们这个配置项的含义,以及如何去配置他。



推荐阅读
  • 本文详细介绍如何在华为鲲鹏平台上构建和使用适配ARM架构的Redis Docker镜像,解决常见错误并提供优化建议。 ... [详细]
  • 协程作为一种并发设计模式,能有效简化Android平台上的异步代码处理。自Kotlin 1.3版本引入协程以来,这一特性基于其他语言的成熟理念,为开发者提供了新的工具,以增强应用的响应性和效率。 ... [详细]
  • 本文详细介绍了Android系统的四层架构,包括应用程序层、应用框架层、库与Android运行时层以及Linux内核层,并提供了如何关闭Android系统的步骤。 ... [详细]
  • 探讨密码安全的重要性
    近期,多家知名网站如CSDN、人人网、多玩、开心网等的数据库相继被泄露,其中大量用户的账户密码因明文存储而暴露无遗。本文将探讨黑客获取密码的常见手段,网站如何安全存储用户信息,以及用户应如何保护自己的密码。 ... [详细]
  • 对象存储与块存储、文件存储等对比
    看到一篇文档,讲对象存储,好奇,搜索文章,摘抄,学习记录!背景:传统存储在面对海量非结构化数据时,在存储、分享与容灾上面临很大的挑战,主要表现在以下几个方面:传统存储并非为非结 ... [详细]
  • 大华股份2013届校园招聘软件算法类试题D卷
    一、填空题(共17题,每题3分,总共51分)1.设有inta5,*b,**c,执行语句c&b,b&a后,**c的值为________答:5 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • Android 构建基础流程详解
    Android 构建基础流程详解 ... [详细]
  • 在 Axublog 1.1.0 版本的 `c_login.php` 文件中发现了一个严重的 SQL 注入漏洞。该漏洞允许攻击者通过操纵登录请求中的参数,注入恶意 SQL 代码,从而可能获取敏感信息或对数据库进行未授权操作。建议用户尽快更新到最新版本并采取相应的安全措施以防止潜在的风险。 ... [详细]
  • Android Studio: 修改应用包名的详细步骤
    本文详细介绍了在Android Studio中如何修改应用的包名,包括具体的操作步骤和注意事项。这对于需要更改包名以适应不同需求的开发者非常有用。 ... [详细]
  • 如何修改360极速浏览器的默认安装路径
    本文介绍了一种有效的方法,帮助用户在新版360极速浏览器中成功更改默认安装路径,解决因权限问题导致的安装失败。 ... [详细]
  • 高端存储技术演进与趋势
    本文探讨了高端存储技术的发展趋势,包括松耦合架构、虚拟化、高性能、高安全性和智能化等方面。同时,分析了全闪存阵列和中端存储集群对高端存储市场的冲击,以及高端存储在不同应用场景中的发展趋势。 ... [详细]
  • 解决Only fullscreen opaque activities can request orientation错误的方法
    本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
  • 在安装 iOS 开发所需的 CocoaPods 时,用户可能会遇到多种问题。其中一个常见问题是,在执行 `pod setup` 命令后,系统无法连接到 GitHub 以更新 CocoaPods/Specs 仓库。这可能是由于网络连接不稳定、GitHub 服务器暂时不可用或本地配置错误等原因导致。为解决此问题,建议检查网络连接、确保 GitHub API 限制未被触发,并验证本地配置文件是否正确。 ... [详细]
  • 数字图书馆近期展出了一批精选的Linux经典著作,这些书籍虽然部分较为陈旧,但依然具有重要的参考价值。如需转载相关内容,请务必注明来源:小文论坛(http://www.xiaowenbbs.com)。 ... [详细]
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社区 版权所有