Linux内核漫游

大爱仙尊 发布于 2026-04-29 192 次阅读


前言

最近突发奇想,想把自己对Linux内核的了解写下来,这个过程顺便增强自己对内核的了解,顺便让大家也能了解一下内核。这篇文章,以白话文形式讲解,我会慢慢查阅资料补充,慢慢的去写,随时都会更新。所以,废话不多说,我们直接开始

漫游的开始-指令

说到指令,大家脑海中有没有想到自己日常生活中,使用电脑时用到的一些快捷键呢?比如保存文件Ctrl+s这种,这种其实也是指令,对吧。在我们的操作系统中,也是有太多太多指令。什么?你说你要全背下来,那可不是一个轻松的事情。指令可以说是特别多,但是这些指令不是靠死记硬背的,你只需要掌握常用的那些指令,然后遇到有些不会的指令了,可以去查。这才是正确的方法,正所谓方向对了,做起来肯定是事半功倍的。说到指令,那么我们就不得不说几个简单的指令了,以便大家了解。这里我直接给大家找了一张图,是一些基础的指令,我这里稍加说明,以便大家的理解。

在这里得给大家稍微科普一下文件这个东西,文件是分为普通文件+目录文件的,那么什么是普通文件呢?什么又是目录文件呢?普通文件就是那些存储数据(文本,二进制)的文件,目录文件是一种特殊的文件,就是用于组织和管理其他文件。就像是你新建了一个文件夹,叫我的心情,然后我的心情里存了很多以时间命名的文件,这些文件中写的就是你所对应的时间的心情。这个我的心情文件夹,就是目录文件,而里面那些以时间命名的文件,就是普通文件。这样说大家肯定都懂了。所以,我们现在回到上面的指令,那些目录所指的,就是文件。比如列出目录内容,就是列出这个目录文件中所有的文件

这里是我执行上面两条代码,大家结合上面的指令功能和文件理解,一定可以看懂,这些显示出来的bin boot等等就是/这个目录文件中的文件,而/就是我们的根目录,一切文件源头一定是他。就像是1生2,2生3,3生万物一样。而现在我要告诉大家两个很重要的东西:1.Linux下一切皆文件2.Linux中目录文件就是上面这种蓝色的,普通文件就是没有特殊颜色这种。而目录文件我们可以cd进入,因为他里面还有文件,这已经是显然易见的了。而这些青色的文件,我们后面会慢慢知道,现在先不做介绍,以免大家思绪混乱。我们继续来说这个指令,这些指令还可以加上后缀,这些都不用记,这种就是用多了,自然会,不会也可以查,唯手熟而。直接来看我的这两个指令有何不同

首先,第一个指令是直接列出了所有文件,第二个加了后缀 -l列出了文件详细信息,这些详细信息就是一些权限的关系,比如前面的rw这种,这个大家学过英语,肯定能联想到读和写,对的,这就是读和写的权力,就是这个文件夹,有读和写的权力就会显示r和w,而为啥是-rw-rw-r--呢?这就是因为,这个服务器可能不是你一个人使用,还可能别人也会使用,而Linux给使用的人分为了三类:

第一类,文件所属者,也就是创建文件的人

第二类,文件所属组,就是属于那个组

第三类,就是other,其他人

而后面的sjy sjy分别就是这个文件的所属者,和所属组,这里显然易见是同一个人,那就是我本人了。因为我的服务器只有我一个人用。说到这里,得跟大家说一个东西,root听过吧,在Linux中,这个是相当于超管,他拥有一切的权限,他可以随便修改别人的东西,也可以删除别人的东西,但是这都是有风险的操作。就像是你去上班,你和张三,李四是一个组,root就像是你们老板,他给你们每个人分配一个身份,你们都可以使用这台服务器来工作,但是root(老板)可以在里面随意修改你们的东西,因为他是老板,他就是牛,而你和张三,李四,互相之间都不可以修改对方的文件,或者删除。除非张三给了你权限,或者是root(老板)给你这个权限。这个时候大家肯定很疑惑,为啥要弄这种权限?这好比你在这个文件中写东西,突然有人也在写,这个时候会不会产生乱码?所以这个权限他是为了互不影响。同时也涉及到了后面的通信等问题。这个我们后面再说,现在你们只要记住,任何文件(目录文件和普通文件)是有权限的,而这个权限是rwx,也就是读写执行,记住这些,就可以了,至于其他的权限如何设置,权限掩码,我们这里不做深入讨论(umask权限掩码),如果后面需要我们再讨论这些。

经过上面的讲解,大家已经可以使用这些最简单的指令,在Linux中进行文件的进入,文件权限的查看,创建文件写入一些简单的文本,对文件有了一个最基本的认识。在有了这些认识后,我们直接进入下一个漫游点

漫游的逐渐深入-进程

说到进程,我们就先得从一个体系开始说起,这个体系就是冯诺依曼体系,如图:

那我们为啥要说到这个体系呢?因为我们常见的计算机,比如笔记本。或者是我们大家不常见的计算器,比如服务器,大部分都遵循这套体系,我们所认识的计算机,都是由一个个硬件来组成的。

输入设备:包括了键盘,鼠标等

中央处理器(CPU):含有运算器和控制器等

输出设备:显示器,打印机等

关于这个冯诺依曼,我们有几个需要知道的:

1.这里的存储器指的就是内存

2.不考虑缓存的情况,这里的CPU能且只能堆内存进行读和写,不能访问外设

3.外设要输入和输出数据,也只能写入内存或者从内存中读取

4.一句话就是,所有的设备都只能直接和内存打交道

这就是我们要了解的冯诺依曼体系的几个点。然后我们再来了解一下操作系统这个东西。

说到操作系统,大家对他的理解是啥样子呢?他的概念就是任何计算机都包含一个基本的程序集合,这便是操作系统,笼统的理解,操作系统包括:

内核:进程管理,内存管理,文件管理,驱动管理

其他程序:比如函数库,shell程序等

那么设置这个操作系统是干嘛的呢?其实很简单,为人服务,这个世界上,不管你创造啥,最终目的都是为了服务人。所以操作系统最主要的,就是方便大家的使用。

操作系统对上:为用户程序(应用程序)提供一个良好的执行环境

操作系统对下:与硬件交互,管理所有的软硬件资源

所以,操作系统就像是你的管家,你买了一个电脑,而操作系统就是你电脑的管家,他会帮你管好所有的东西,方便你的使用。再这里问下大家,那么如何管理这些东西呢?

我们举一个例子:上面是不是跟大家讲过一个目录文件和普通文件,那么大家仔细想一下,不管是啥东西,是不是都包括两个东西:内容+属性,不管啥文件,要有内容,就是你文件写的那些。属性就是文件创建时间,文件的大小等,这些是不是都是属性。

那么比如现在你是一个学生,你是不是也会有这两个东西:内容+属性。内容就是你这个人这些年发生过啥事,比如你上小学在老家,然后初中到了市里,然后上大学来到了大城市。那么属性就是你的岁数,你的身份证号,你是男的女的,这些统称为属性。那现在回到我们上面问的,我们如何管理这些东西呢?

记住一句话:先描述,再组织。这就是管理的方式。

比如你上大学了,你要填表,姓名,性别,年龄,住址,电话等等。这就是先描述,然后每一个大学生都要填,最后把这些组织到一起,给你们每一个人分配一个学号。这就是先描述,再组织。计算机世界的很多设计,其实都是跟生活息息相关。现在理解起来是不是很简单了。

那么现在我问大家一个问题,操作系统是如何管理进程的呢?很简单,先把进程描述起来,然后把进程组织起来。先描述,再组织。说到进程,得说一下他的英文名称-PCB,课本上就这样称呼的。Linux操作系统下的PCB是:task_struct(task_struct-PCB的一种),task_struct是啥呢,大家估计一看就懂了,这不就是个结构体吗?那这个里面很显然,就是进程的属性。那他里面的内容是啥呢?我们来看看:

标识符:描述进程的唯一标识符,就像是你上学有一个唯一的学号,用来区别你和其他人

状态:任务状态,退出代码,退出信号等

优先级:相对于其他进程的优先级

程序计数器:程序中即将被执行的下一条指令的地址

内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享内存块的指针

上下文数据:进程执行时处理器的寄存器中的数据

I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表

记账信息:可能包括处理器时间总和,使用的时钟数总和

其他信息:等等

我们先来说一说进程的标识符:也就是pid(进程id),父进程的id(ppid)。然后我们可以使用系统调用函数fork()来创建进程,创建出来的进程也就是子进程,他会有自己的pid,然后他的ppid就是创建他这个进程的pid,所以创建出来的进程,也就叫做子进程,创建他的进程,就叫做父进程。然后父子进程的代码是共享的,数据是各自开辟空间,私有一份(采用的是写时拷贝)。

我们再来说说进程的状态:这里给出的是进程的5状态模型(常用)

为了搞懂进程的这些状态,得向大家抛出一些概念性的东西,这里我直接给大家给出图片,大家自己看:

这里简单的带大家过一遍这个流程,我们不讨论进程创建失败,就是进程先创建,然后这个时候还未加载到内存,然后这个时候就进入到就绪状态了,进程就在等待调度,然后等到后,就到运行状态,在CPU上执行对应的指令,然后如果别的进程正在使用CPU调度,这个时候这个进程可能会进入阻塞状态,然后最后一种就是进程结束,需要回收进程,如果没有回收,这个时候进程就是僵尸状态,然后回收成功才是死亡状态。

这里涉及到的知识太多,我们一条一条来梳理。首先这些状态:

这里先说一个结论,就是一般子进程的回收,是由父进程做的

僵尸状态:子进程运行完,但是子进程没有人管理,没人回收,父进程没回收,就是僵尸状态

孤儿状态:创建这个子进程的父进程已经被回收,但是子进程需要父进程回收,父进程已经没了,这个时候,子进程就是一种孤儿状态。一般这种进程会由1号进程(systemd)来领养,然后回收,1号进程是首个用户态进程。

我们再来说一说进程的优先级

优先级这个东西,大家一听都很容易理解,就是大家常说谁先谁后,那么为啥进程要有优先级呢?其实很好理解,你想啊,cpu是不是要调度进程,但是有那么多进程,谁先谁后呢?就像你找别人办事,你说你的事情很重要,难道别人的事情不重要吗?是不是调度起来会导致不公平。所以,cpu这个时候就是资源,所谓是资源就会有竞争,这个时候这些进程就会来竞争cpu这个资源,谁竞争到了,谁就优先调度,优先执行。所以优先级这个东西,不是谁研究出来的,他就像是顺势而生,就是他的出现,不是偶然,而是必然。所以进程的优先级是可以设置的,优先级高的先执行,低的后执行。

然后我们这里补充一个概念:竞争,并发,并行,独立

竞争性:进程数量众多,而CPU资源只有少量,甚至一个,所以进程之间是有相互竞争属性的,为了高效完成任务,合理竞争资源,便有了优先级

并发性:多个进程在同一个CPU下采用进程切换的方式,在同一段时间内,让多个进程推进,这就是并发

并行性:多个进程在多个CPU下分别,同时运行,,这就是并行

独立性:多进程运行,需要独享各种资源,多进程运行时互不干扰,这就是独立。

补充完这个我们来聊一聊进程切换,首先进程切换,这个听起来就是很容易理解,就是进程运行一会然后切换另一个进程。听起来容易,但是CPU中这个过程还是有点麻烦的,首先,要明白的一件事:CPU中寄存器是只有一份的。比如现在进程A正在运行,这个时候进程B来了,要切换进程,那么进程A就得把CPU上寄存器的数据打包带走,保存起来,方便下一次回来的时候,能按照之前的逻辑继续执行,所以CPU中上下文数据是有很多份的,分别对应不同的程序。

说到这里,我们又不得不抛出一个概念:时间片

时间片是啥呢?其实就是一个计数器,当代计算机都是分时操作系统,每个进程有他的时间片,时间片到达,进程就得被操作系统从CPU上剥离下来。

这里给大家说一下,内核中进程调度其实是两个数组,按照优先级在一个数组中排列好,然后执行完的进程,会到另一个数组中,这是为了公平起见,让每一个进程都会被CPU调度到,这叫进程调度O(1)算法。这里我必须为这个算法的设计说一句。调度至此,已是化境。哈哈哈

说完了这些,我们来谈一谈进程的地址空间,那么我们该如何去理解进程的地址空间呢?大家学习语言的时候,肯定见过这张图:

这个就是学习语言的时候说的内存空间,这里我直接说结论,就是这个地址并不是真正意义上的物理地址,他就是一个虚拟地址,我们用c/c++看到的所有地址,全部都是虚拟地址,物理地址,用户一概看不到,由操作系统统一管理。那么我们说这个肯定是因为他和我们后面的进程有关系。那么进程的地址空间是咋样的呢?这里我找了一张图:

我们一般看到的就是左边的虚拟地址,而他会通过页表映射到物理地址,这个页表中存的就是物理地址和虚拟地址的映射关系,这里其实页表不是看上去这样子,但是我们现在这里先这样理解是没有问题的。他就是一个映射地址的表。

这里得说一个事,首先,物理地址肯定是只有一份的对吧。但是有很多进程,他们是如何合理安排内存分配的呢?这里就不得不告诉大家,其实每一个进程创建出来的时候,都会有一个虚拟内存这样的表。这里给大家举个例子:土豪的例子

就是现在有一个土豪,他有10个亿,然后这个土豪是一个私生活及其不检点的人,他有一个老婆,生了一个孩子,然后他还和外面的比如,小美1,小美2,小美3,这三个女生,每个都生下了一个私生子。他现在就有四个孩子,这里给大家一张图,用来理解这个关系:

现在这个土豪就是身体不行了,然后他就想在离开前,看看他的四个孩子。这里要说的是这四个孩子都肯定是不知道土豪还有别的孩子的存在。然后土豪去看孩子1,就告诉孩子1,我马上要走了,我把我的钱都留给你,然后他依次对这四个孩子说了同样的话。但是土豪实际上,早就想好了,到时候自己死了,把自己钱平分给这四个孩子,让他们也相认一下。但是这四个孩子不知道啊,每个都幻想这个老登死了,自己就有10个亿了。用我们现在的话来说,这土豪就像是一个领导,给这四个孩子(下属)画大饼。说你好好干,我到时候给你升职加薪。

看完这个故事,我们想一下,其实进程就是这四个孩子,而土豪就是我们的操作系统,他给每个进程说,你们每个人都独享这个地址空间,每个进程都信以为真。那有人问了,这操作系统不是骗人吗?给这四个进程画大饼。对,没问题,就是画大饼。给每个进程一个虚拟地址空间,当你这个进程要使用这块空间的时候,才通过页表映射虚拟地址到物理地址,不使用的时候,其实就没占用空间,也没有给你真的创建这块空间。这样是不是大大提高了内存的使用率。

总的来说就是,操作系统给进程画大饼,你不用空间的时候,我就不给你空间,当你使用的时候,我才给你分配对应的空间。这里顺带提一下:对语言有了解的人,知道写时拷贝的人,看完这个就懂了写时拷贝的原理。其实就是这样。

这里再说一下,描述进程地址空间所有信息的就是一个结构体,这个结构体就是mm_struct(内存描述符)。每个进程都有一个,这个结构体在task_struct结构中,有一个指向该进程的mm_struct指针。那么这个mm_struct肯定也是要组织起来的,又是那句先描述,再组织

那为啥要有这个虚拟地址空间?这个问题其实转化为直接使用物理地址空间有什么问题吗?

1.安全风险:每个进程如果能直接随意访问物理地址空间,这也就意味着进程可以随意在物理地址空间中读写,那么如果是一个木马病毒,可能随意的修改,会导致系统直接瘫痪。

2.地址不确定:大家都知道,程序是放在硬盘上的,当运行的时候,就会把程序搬运到内存中去运行,如果直接使用物理地址的话,我们无法确定内存使用到哪里了,也就是说拷贝的实际内存地址每一次运行都是不确定的。

3:效率低下:这样会导致经常出现内存拥挤的情况,然后腾出内存会很麻烦,效率肯定是不高的,所以有了虚拟内存和页表以后,这些问题就可以得到很好的解决,所以,虚拟内存和这个页表的产生也是顺其自然。但是能想出来这个东西的人不得不说很厉害。这世间真是英才无数,哈哈。

漫游的回溯-重谈指令

又回到了开始,我们又要说到指令了,但是这次是探寻本源,我们来重新看看指令的底层到底是怎样的。

此作者没有提供个人介绍。
最后更新于 2026-05-05