Menu Close

什么是Linux内核?内核在操作系统中的作用是什么

Linux 内核概述

Linux® 内核是 Linux 操作系统(OS)的主要组件,也是计算机硬件与其进程之间的核心接口。它负责两者之间的通信,还要尽可能高效地管理资源。

之所以称为内核,是因为它在操作系统中就像果实硬壳中的种子一样,并且控制着硬件(无论是电话、笔记本电脑、服务器,还是任何其他类型的计算机)的所有主要功能。

内核的作用是什么?

内核有 4 项工作:

  1. 内存管理:追踪记录有多少内存存储了什么以及存储在哪里
  2. 进程管理:确定哪些进程可以使用中央处理器CPU)、何时使用以及持续多长时间
  3. 设备驱动程序:充当硬件与进程之间的调解程序/解释程序
  4. 系统调用和安全防护:从流程接受服务请求

在正确实施的情况下,内核对于用户是不可见的,它在自己的小世界(称为内核空间)中工作,并从中分配内存和跟踪所有内容的存储位置。用户所看到的内容(例如 Web 浏览器和文件)则被称为用户空间。这些应用通过系统调用接口(SCI)与内核进行交互。

举例来说,内核就像是一个为高管(硬件)服务的忙碌的个人助理。助理的工作就是将员工和公众(用户)的消息和请求(进程)转交给高管,记住存放的内容和位置(内存),并确定在任何特定的时间谁可以拜访高管、会面时间有多长。

如何理解内核在操作系统中的位置?

为了更具象地理解内核,不妨将 Linux 计算机想象成有三层结构:

  1. 硬件:物理机(这是系统的底层结构或基础)是由内存(RAM)、处理器(或 CPU)以及输入/输出(I/O)设备(例如存储、网络和图形)组成的。其中,CPU 负责执行计算和内存的读写操作。
  2. Linux 内核:处于操作系统的核心位置。驻留在内存中的软件,用于告诉 CPU 要执行哪些操作。
  3. 用户进程:这些是内核所管理的运行程序。用户进程共同构成了用户空间。用户进程有时也简称为进程。内核还允许这些进程和服务器彼此进行通信(称为进程间通信或 IPC)。

系统执行的代码通过以下两种模式之一在 CPU 上运行:内核模式或用户模式。在内核模式下运行的代码可以不受限制地访问硬件,而用户模式则会限制 SCI 对 CPU 和内存的访问。内存也存在类似的分隔情况(内核空间和用户空间)。这两个小细节构成了一些复杂操作的基础,例如安全防护、构建容器和虚拟机的权限分隔。

这也意味着:如果进程在用户模式下失败,则损失有限,无伤大雅,可以由内核进行修复。另一方面,由于内核进程要访问内存和处理器,因此内核进程的崩溃可能会引起整个系统的崩溃。由于用户进程之间会有适当的保护措施和权限要求,因此一个进程的崩溃通常不会引起太多问题。

Linux内核架构(内核地图)

Linux内核地图
Linux内核地图

Linux是一个单体内核,支持真正的抢占式多任务处理、虚拟内存、共享库、请求分页(英语:Demand paging)、共享写时复制可执行体(通过内核同页合并(英语:Kernel same-page merging))、内存管理、Internet协议族和线程等功能。

设备驱动程序和内核扩展运行于内核空间(在很多CPU架构中是ring 0),可以完全访问硬件,但也有运行于用户空间的一些例外,例如基于FUSE/CUSE的文件系统,和部分UIO。多数人与Linux一起使用的图形系统不运行在内核中。与标准单体内核不同,Linux的设备驱动程序可以轻易的配置为内核模块,并在系统运行期间可直接装载或卸载。也不同于标准单体内核,设备驱动程序可以在特定条件下被抢占;增加这个特征用于正确处理硬件中断并更好的支持对称多处理。出于自愿选择,Linux内核没有二进制内核接口。

硬件也被集成入文件层级中。用户应用到设备驱动的接口是在/dev或/sys目录下的入口文件。进程信息也通过/proc目录映射到文件系统。

 

Linux内的各种层,还显示了在用户空间和内核空间之间的分离。
用户模态 用户应用 例如:Bash,LibreOffice,GIMP,Blender,0 A.D.,Mozilla Firefox等
低层系统构件 系统守护进程:
systemd,runit,logind,networkd,PulseAudio等
窗口系统:
X11,Wayland,SurfaceFlinger(Android)
其他库:
GTK+, Qt, EFL, SDL, SFML, FLTK, GNUstep等
图形:
Mesa,AMD Catalyst等
C标准库 open()exec()sbrk()socket()fopen()calloc(),… (直到2000个子例程)
glibc目标为POSIX/SUS兼容,musl和uClibc目标为嵌入式系统,bionic为Android而写等
内核模态 Linux内核 statsplicedupreadopenioctlwritemmapcloseexit等(大约380个系统调用)
Linux内核系统调用接口(SCI,目标为POSIX/SUS兼容)
进程调度子系统 IPC子系统 内存管理子系统 虚拟文件子系统 网络子系统
其他构件:ALSA,DRI,evdev,LVM,device mapper,Linux Network Scheduler,Netfilter
Linux安全模块:SELinux,TOMOYO,AppArmor, Smack
硬件(CPU,内存,数据存储设备等。)

编程语言

Linux是用C语言中的GCC版(这种C语言有对标准C进行扩展)写的,还有几个用汇编语言(用的是GCC的”AT&T风格”)写的目标架构短段。因为要支持扩展的C语言,GCC在很长的时间里是唯一一个能正确编译Linux的编译器。有许多其他的语言用在一些方面上,主要集中在内核构建过程中(这里指从源代码创建可启动镜像)。包括Perl、Python和多种脚本语言。有一些驱动可能是用C++、Fortran或其他语言写的,但是这样是强烈不建议的。

编译器兼容性

GCC是Linux内核源代码的缺省编译器。在2004年,Intel主张通过修改内核,以便Intel C++编译器能正确编译内核。[33]在2009年,有通过修改内核2.6.22版而成功编译的报告(并带来平均8-9%性能增长)。

自从2010年,已经开始进行使用Clang建造Linux内核的努力,Clang是一个可作为替代的C语言编译器;截止2014年4月12日,官方内核几乎可以完全用Clang编译。致力于这个目标的计划叫做“LLVMLinux”,得名于Clang所基于的LLVM编译器下部构造。LLVMLinux不意图复制Linux内核或LLVM,因此它是由最终提交给上游计划的补丁构成的一个元计划。使Linux内核可以用Clang编译最大的好处是比GCC有更快的编译速度,内核开发者可以得益于由此而来的更快的工作流程。

接口

区分四种接口:两种内核内部,两种在内核和用户空间之间
区分四种接口:两种内核内部,两种在内核和用户空间之间
区分四种接口:两种内核内部,两种在内核和用户空间之间。

符合标准是Linux内核内部的普遍策略。另一个规则是Linux内核主线不接受只由专有用户空间软件使用的内核模块。

内核至用户空间API

Linux API组成自Linux内核的系统调用接口、GNU C函数库、libcgroup、libdrm、libalsa和libevdev
Linux API组成自Linux内核的系统调用接口、GNU C函数库、libcgroup、libdrm、libalsa和libevdev

源代码可移植性确保符合标准的C程序可以在符合同样标准的任何系统上编译和运行。Linux内核开发、GNU C函数库和相关的实用工具致力于追随POSIX和单一UNIX规范。Linux内核API(英语:Linux kernel interfaces)是内核的系统调用接口。

二进制可移植性将保证任何程序在符合标准的给定硬件平台上一旦编译通过,可以在符合同样标准的任何其他硬件平台上以编译后的形式运行。二进制可移植性是在基于Linux内核的操作系统上建造独立软件供应商(ISV)应用有商业可行性的本质要求。现有唯一的二进制兼容标准是Linux标准规范(LSB)。

内核内API

图形的数据和指令被发送至GPU来处理。渲染呈现的结果被存储在帧缓冲器,其中的内容由视频显示控制器扫描并发送至屏幕。
图形的数据和指令被发送至GPU来处理。渲染呈现的结果被存储在帧缓冲器,其中的内容由视频显示控制器扫描并发送至屏幕。

 

在不同子系统间使用了数个内核内部API。其中一些是跨越多个发行版保持稳定的,另一些则不然。对于内核内API不作担保。维护者和贡献者可以在任何时候增加或变更它们。

内核内API的例子包括针对下列类别设备驱动程序的软件框架/API:

  • Video4Linux – 用于视频捕捉硬件。
  • 高级Linux声音体系(ALSA) – 用于声卡。
  • New API(英语:New API) – 用于网络接口控制器。
  • 直接渲染管理器(英语:Direct Rendering Manager) – 用于图形加速器。
  • KMS驱动器(英语:KMS driver) – 用于视频显示控制器(英语:Video display controller)。
  • mac80211 – 用于无线网络接口控制器[44]。

Linux内核技术特性

抢占式调度系统

Linux内核提供在特定条件下的抢先式调度。直到内核版本2.4,只有用户进程是抢先式的,就是说除了时间片用尽,在用户模式下执行的当前进程,如果有更高态优先级的进程进入TASK_RUNNING状态,它就会被中断。自从2.6系列Linux内核,增加了中断执行内核代码的任务的能力,但不是对于内核代码的所有段落。

I/O调度器在Linux内核存储栈各层内的位置
I/O调度器在Linux内核存储栈各层内的位置

Linux内核含有不同的调度器类。内核缺省使用的调度机制叫做完全公平调度器,它介入于内核版本2.6.23。这个缺省调度器类在内部也叫做SCHED_OTHER,而内核还含有两个遵循POSIX的实时调度类,分别叫做SCHED_FIFO(实时先进先出)和SCHED_RR(实时轮流式),二者都优先于缺省类。

通过使用实时Linux内核补丁PREEMPT_RT,可以支持对关键段落、中断处理器和“中断禁用”代码序列的完全抢先。 实时Linux内核补丁部分地集成入主线内核已经带给它一些功能。抢先机制改善延迟、增进响应性,并使得Linux更加适合桌面和实时应用。老版本内核有所谓的巨锁(英语:Giant lock),用于锁定粒度为整个内核的同步,它最终由Arnd Bergmann在2011年移除了。

还有叫做SCHED_DEADLINE(英语:SCHED_DEADLINE)的调度策略,实现了最近截止期限最先(英语:earliest deadline first scheduling)(EDF)算法,它增加于2014年3月30日发行的内核版本3.14。

Linux内核可移植性

尽管林纳斯·托瓦兹的初衷不是使Linux成为一个可移植的操作系统,今天的Linux却是全球被最广泛移植的操作系统内核。从移动电话到超级电脑,甚至于有人成功的将Linux内核在索尼出品的游戏机PS2及PS3和微软出品的游戏机Xbox上使用。Linux也是IBM超级计算机Blue Gene的操作系统。直至2011年11月,全球前五百大超级电脑(TOP500)有高达91.4%的比例采用Linux为它们的操作系统。一些为手机开发的操作系统,使用Linux内核的修改后的版本,其中包括谷歌Android、Firefox OS、HP WebOS和诺基亚Maemo。

内核错误和oops

Linux 内核错误(Kernel panic)
Linux 内核错误(Kernel panic)

在Linux中,内核错误(Kernel panic)是指操作系统在监测到内核系统内部无法恢复的错误,相对于在用户空间代码类似的错误。操作系统试图读写无效或不允许的内存地址是导致内核错误的一个常见原因。内核错误也有可能在遇到硬件错误或操作系统BUG时发生。在许多情况中,操作系统可以在内存访问违例发生时继续运行。然而,系统处于不稳定状态时,操作系统通常会停止工作以避免造成破坏安全和数据损坏的风险,并提供错误的诊断信息。

在Linux上,oops即Linux内核的行为不正确,并产生了一份相关的错误日志。许多类型的oops会导致内核错误,即令系统立即停止工作,但部分oops也允许继续操作,作为与稳定性的妥协。这个概念只代表一个简单的错误。当内核检测到问题时,它会打印一个oops信息然后杀死全部相关进程。oops信息可以帮助Linux内核工程师调试,检测oops出现的条件,并修复导致oops的程序错误。

linux内核的安全

计算机安全是一个非常公众化的主题,关系到Linux内核,因为大量在内核中的错误可能成为潜在的安全漏洞,是否允许提升权限漏洞或拒绝服务攻击源漏洞。在过去的几年中,许多这样的缺陷被发现,并在Linux内核中被修补好。新的安全功能被继续实现,以解决在Linux内核中的电脑不安全问题。

批评者指责内核开发人员,称他们掩盖(至少并未公布)安全漏洞。2008年,作为回应,Torvalds称:“个人认为,安全漏洞只是‘正常的漏洞’。这些漏洞我并不去掩盖,不过我不认为应当把它们特殊化,更不认为应该追踪并公示它们……我不理会整个安全团队,原因之一就是,我认为这些漏洞不仅美化还鼓励了错误的行为。这令安全人员成了‘英雄’,就犹如不修补正常漏洞的人就不值一提似的。而事实上,所有无聊的正常漏洞极为重要,仅仅因为它们实在太多了。我不认为该美化和关心那些严重的安全漏洞——它们并不及那些由死锁造成的随机严重崩溃来得更特殊。”

如2012年五月,SYSRET指令被发现在AMD英特尔处理器间在实现方面有差异,这个差异在Windows、FreeBSD、XenServer和Solaris这些主流操作系统会导致漏洞。2012年六月,Linux内核中该问题已被修复。

READ  下载后安装Oracle VM VirtualBox

2021年,来自明尼苏达大学的研究人员,曾借由贡献补丁至Linux内核的名义,利用补丁导入臭虫或漏洞,以观察Linux内核社群的反应,再度故技重施时,被发现后屏蔽了所有来自该大学的贡献,与移除过去该大学曾经贡献的代码。

Linux内核的发展史

1991年,林纳斯·托瓦兹,一名21岁的就读于芬兰赫尔辛基大学的计算机科学专业学生,基于一些简单的想法,打算编写一个操作系统内核。他通过英特尔80386汇编语言的任务切换器和一个终端驱动程序开始工作。8月25号,他在comp.os.minix新闻组里发了一封帖子:

我在做个(自由的)操作系统(就是个兴趣爱好,我不会搞得像GNU那么大那么专业),打算让它工作在386 AT平台上。它从四月就开始酝酿了,马上就快好了。我想要那些喜欢或不喜欢minix的人的意见,因为我的系统和它有点类似(同样的文件系统的物理布局——由于实际原因——还有些其他的东西)。

我现在已经移植了bash(1.08)和gcc(1.40), 而且看起来奏效了。这意味着我会在几个月内得到一些实用的东西。“……”是的——它没有任何minix代码,并且它有一个多线程的fs。它可移植(使用386任务切换等),而且它可能永远不会支持除AT硬盘之外的其他东西,因为我只有这些:-(。

“……”它基本上是用C语言写的,但是大多数人可能不会把我写的东西叫做C语言。它使用我能找到的386的每个可以想象的特性,因为它也是一个教我关于386的功能的项目。我前面提到过,它使用内存管理单元来进行分页(还没实现到对硬盘的功能)和分段。这个分段功能使得它真正的依赖于386(每个任务都有64Mb的代码和数据段——4Gb中最多64个任务。如果有人需要超过每个任务64Mb的限制,那将是个麻烦事)。“……”我的一些C语言文件(特别是mm.c)几乎用了和C一样多的汇编。“……”不像minix,我也碰巧喜欢中断,所以中断将在不试图隐藏背后的原因的情形下被处理。

之后,许多人为这个项目贡献了代码。在早期,MINIX社区向 Linux 内核贡献了代码和想法。当时,GNU 项目已经创建了许多自由操作系统所需的组件,但是它自己的内核 GNU Hurd 尚不完整且无法使用;而BSD操作系统还没有摆脱合法的阻碍。因此,尽管早期版本的 Linux 功能有限,但它迅速获得了开发人员和用户。

到1991年9月,Linux内核版本 0.01 在芬兰大学和研究网络(FUNET)的FTP服务器(ftp.funet.fi)上发布。它有10,239行代码。在1991年10月,0.02版本的内核发布了。

1991年12月,0.11版本的内核发布。由于它可以由运行相同内核版本的计算机编译,因此该版本是第一个自托管的英语Self-hosting Linux 内核。当托瓦兹于1992年2月发布0.12版本时,他采用了 GNU 通用公共许可证(GPL),而不是以前的自行起草的许可证,原先的许可证不允许商业再分发。

1992年1月19日,第一篇文章提交给新的新闻组alt.os.linux出现。1992年3月31日,该新闻组更名为 comp.os.linux

X Window 系统随后被移植到Linux上,所以在1992年3月,Linux 0.95 是第一个能够运行X的版本。从0.1x到0.9x的版本号大幅跨越是因为期望没有大的缺失部分的版本1.0的即将出现。然而,这被证明是错误的。从1993年到1994年初,出现了0.99版本的15个开发版本。

1994年3月14日,Linux内核1.0.0发布,共176,250行代码。随后的1995年3月,有310,950行代码的 Linux 内核1.2.0发布。

在1996年6月9日发布的 Linux内核2.0版本之后,以2.0为大版本的主要更新有如下这些:

  • 1999年1月25日 – 发布Linux内核2.2.0(1,800,847行代码)
  • 1999年12月18日 – 针对2.2.13的 IBM 大型机补丁发布,允许 Linux 内核用于企业级机器
  • 2001年1月4日 – 发布 Linux 内核2.4.0(3,377,902行代码)
  • 2003年12月17日 – 发布 Linux 内核2.6.0(5,929,913行代码)

从2004年开始,发布过程发生了变化,新的内核每隔2-3个月定期发布,编号为2.6.0、2.6.1,直到2.6.39。

2011年7月21日,Torvalds宣布发布Linux内核3.0:“2.6.<大版本> 的日子过去了”。与Linux 2.6.39相比,大的技术变化同版本跃升没有关系;它标志着内核的20周年纪念。基于时间的发布过程保持不变。

2013年6月发布的Linux内核版本3.10包含15,803,499行代码[22],而2015年6月发布的4.1版本已发展到超过1950万行代码,由近14000名程序员贡献。

除教程外,本网站大部分文章来自互联网,如果有内容冒犯到你,请联系我们删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Leave the field below empty!

Posted in Linux 教程

Related Posts