终于,我们走到了Linux的第二部分。随着学习的不断深入,这段旋律正不可阻挡地推向它的第一个高潮。Linux的学习版图,大致可以归结为几个核心话题。而今天,我们正式踏入其中最硬核、也最迷人的一个领域——进程。准备好了吗?我们开始。

                                        

目录

一、操作系统的起点:冯诺依曼体系结构

1.1 初识计算机体系结构

1.1.1 软件运行的基础条件

1.1.2 计算机内部存储层级与读写速度

1.1.3 数据流动与计算机体系结构

二、认识操作系统:连接软件与硬件的核心桥梁

2.1 操作系统的基本概念

2.1.1 操作系统到底是什么?

2.1.2 Linux内核、Android与手机操作系统的关系

三、操作系统的核心目标——管理资源与提供服务

3.1 软硬件体系的层次化结构

3.1.1 什么是软硬件层状结构?

3.1.2 深入拆解软硬件交互流程

3.1.2.1 系统调用——用户访问内核的唯一通道

3.1.2.2 驱动程序——连接内核与硬件的桥梁

3.2 总结——软硬件体系结构中的调用链路

四、操作系统的管理哲学:先描述,再组织

4.1 第一阶段:建立管理模型——从实体到数据

4.2 第二阶段:抽象对象模型——通过结构体完成描述

4.3 第三阶段:组织数据模型——通过数据结构实现管理


一、操作系统的起点:冯诺依曼体系结构

1.1 初识计算机体系结构

我们日常使用的笔记本、码农案头的开发机,以及云端沉默运转的服务器,无论形态如何,绝大多数都遵循同一套设计蓝图,冯诺依曼体系结构

到目前为止,我们所接触的计算机,本质上都是由一个个独立的硬件组件拼装而成,各司其职:

  • 输入单元:键盘、鼠标、触摸板、摄像头、扫描仪……它们是计算机感知外界信息的触角,负责把物理世界的动作转化成数字信号。
  • 中央处理器(CPU):包含运算器和控制器,是整个系统的“大脑”。运算器负责加减乘除逻辑运算,控制器负责解析指令、调度各部件协同工作。
  • 输出单元:显示器、打印机、扬声器等,把计算机处理后的结果用人类能感知的方式呈现出来。
  • 存储器:这里的存储器通常指内存(RAM),是程序运行时的临时数据驿站。而ROM则存放固化的基础程序,掉电不丢失。

关于磁盘和网卡,它们身份比较特殊,既负责读,也负责写,兼具输入和输出的双重属性。关于它们在体系结构中的具体定位和运转机制,我们后面会单独展开讲。

1.1.1 软件运行的基础条件

一个程序在跑起来之前,它安安静静地躺在磁盘上,可能是一个可执行文件,也可能是一堆库文件和资源文件的集合。磁盘,在这个体系结构里称为“外存”,是数据的永久居所。

但程序不能直接从磁盘上被执行。它必须先经历一步关键的迁移——加载到内存

内存,就是冯诺依曼蓝图中那块“存储器”。它是CPU与外界交换数据的必经之路。这条规则背后的原因直接且唯一:CPU获取指令和写入数据,只能通过内存来进行。

CPU的物理引脚只跟内存总线通信,它的指令集架构决定了它无法绕过内存直接去访问磁盘上的数据。代码在执行时,每一条指令、每一个变量,都是CPU从内存里抓取或写入的。磁盘只是“仓库”,内存才是“工作台”,CPU要从工作台上取零件、组装、再放回去,而把零件从仓库搬上工作台,就是“加载”这一步必须完成的使命。

结论很简单:软件在运行前,必须先加载到内存。 这不是设计偏好,而是冯诺依曼架构下的物理铁律。从操作系统角度看,这个加载过程就是“创建进程”的核心环节之一,一个程序从磁盘文件,变成内存中一个活生生的进程,第一步就是被装入内存。后面讲到进程的创建与调度时,这条逻辑链会反复出现。

这一切的根源,都指向冯·诺依曼体系结构定下的那条硬件铁律:所有设备,都只能直接和内存打交道。 外设要输入或输出数据,也必须先写入内存,或从内存中读取。没有例外。

继续追问一层:为什么 CPU 非要通过内存,不能直接指挥磁盘和外设?

决定因素:体系结构的整体效率,是由设备间的“拷贝”速度决定的。

这里有一个残酷的物理现实:CPU的速度量级是纳秒级,而磁盘等外设的速度量级是毫秒级,两者之间横亘着数个数量级的鸿沟。如果让CPU直接去读写磁盘,就相当于逼一匹千里马用蜗牛的速度爬行。计算机内部同样遵循木桶效应:最慢的那块木板,决定了整个系统的实际水位。内存,正是卡在CPU和磁盘之间那块精心设计的“缓冲木板”,它的读写速度介于两者之间,快过磁盘几个数量级,刚好能喂饱CPU的指令流水线。

                                ​​​​​​​        

所以,程序必须先从磁盘“搬”到内存,再由CPU从内存中取指令执行。这正是缓冲区存在的底层逻辑——本质上,计算机内部数据的流动,就是从一个设备“拷贝”到另一个设备的连续过程。从磁盘拷到内存,从内存拷到CPU寄存器,再从寄存器拷回内存,周而复始。理解了“拷贝”这两个字,就理解了冯诺依曼架构下数据流转的全部秘密。

1.1.2 计算机内部存储层级与读写速度

顺着“拷贝效率决定系统性能”这条线索,自然就引出了“读写速度”这个关键概念。计算机内部的存储设备,从上到下可以排成一座经典的金字塔:

  • 塔尖是CPU寄存器,纳秒级的访存延迟,跟CPU同频共振,是整台机器里最快的存储单元。

  • 往下是CPU缓存(L1/L2/L3),静态RAM工艺,几十纳秒到几纳秒级,用来缓冲内存中最热的数据。

  • 再往下是 内存(RAM),百纳秒级,虽然跟CPU差了两个数量级,但已经比磁盘快了好几个数量级。

  • 最底层是 磁盘(SSD/HDD)和网卡等外设,毫秒级起步,跟CPU之间隔着数万倍的延迟。

这座金字塔,其实是物理成本和性能之间的博弈结果。寄存器最快,但贵得按比特算;磁盘最便宜,但慢得按毫秒等。如果全用寄存器,一台电脑的价格能买下一栋楼;如果全用磁盘,开机就要等一整天。现代计算机的巧妙之处,正是在这座金字塔上做足了性价比,用昂贵的器件做少量的事,用便宜的器件做大量的事,中间靠内存做缓冲和调度,这才有了今天又快又用得起的计算设备。

1.1.3 数据流动与计算机体系结构

抽象地讲“拷贝”可能有点枯燥,恰好有一个现成的例子能让这条数据链路一目了然。

假设现在Mr.Zc通过键盘敲了一段话,想通过网络发给Mr.List。这段数据在计算机内部到底走了怎样一条路?

在Mr.Zc的机器上:

  • 键盘(输入设备)把按键信号转化为数据,拷贝到内存。
  • 如果附带文件,文件从磁盘(外存)拷贝到内存。
  • CPU从内存中读取数据,处理封装后,再拷贝回内存中的网络缓冲区。
  • 网卡(输出设备)从内存取走数据,转化为电信号或光信号,抛向网络。

在Mr.List的机器上:

  • 网卡(输入设备)接收到信号,把数据拷贝到内存。
  • CPU从内存读取数据,解析处理后,再拷贝到显存或磁盘缓冲区。
  • 显示器(输出设备)从显存取数据显示在屏幕上,或磁盘将文件持久化保存。

看出来了吗?这一整条链路,拆解到底,就是一次又一次的“拷贝”——从外设拷到内存,从内存拷到CPU,再从内存拷回外设。所有设备都围着内存转,没有谁能绕过内存直接对话。

而站在更宏观的视角看,这本质上是两个冯诺依曼体系结构之间的交互。每台机器各自遵循“外设 → 内存 → CPU → 内存 → 外设”的内循环,两台机器之间则通过网卡这个特殊外设,把内循环的数据“甩”到网络上去,由另一台机器接住,开启它的内循环。整个互联网的通信,说到底,就是无数台冯诺依曼机器之间,由“拷贝”串联起来的数据接力。

二、认识操作系统:连接软件与硬件的核心桥梁

2.1 操作系统的基本概念
2.1.1 操作系统到底是什么?

任何一台计算机,都离不开一个核心的软件系统,操作系统(Operating System,简称OS)。它就像计算机世界里的“总管家”,负责协调硬件资源与软件程序之间的关系,让各种应用能够稳定、高效地运行。从广义角度来看,一个完整的操作系统通常包含以下几个部分:

  • 计算机硬件:包括CPU、内存、磁盘、输入输出设备等,是整个系统运行的物理基础;
  • 内核(Kernel):操作系统最核心的部分,负责管理计算机中的关键资源,例如进程管理、内存管理、文件管理以及驱动管理等;
  • 其他系统程序:例如函数库、Shell命令解释器等,为用户和应用程序提供更加方便的操作接口。

换一个角度理解,广义上的操作系统可以看作:操作系统 = 内核 + 一系列配套系统程序,不过,在实际学习和讨论中,我们经常会遇到另一种更狭义的说法:操作系统 = 内核,这种观点更加关注操作系统最核心的功能,也就是对硬件资源的管理能力。在后续Linux的学习过程中,我们默认采用这个狭义定义,将内核(Kernel)视为操作系统的核心,重点围绕 Linux 内核如何管理计算机资源,以及用户如何通过Shell等工具与内核进行交互展开。

2.1.2 Linux内核、Android与手机操作系统的关系

很多人第一次接触Linux时,都会产生一个疑问:Linux、安卓以及手机厂商的系统,到底是什么关系?其实三者并不是并列存在,而是一种层层构建的关系,可以形象地理解为:

Linux内核是地基,安卓是毛坯房,各大厂商系统则是在其基础上装修后的精装房。

在这个体系中,最底层的是Linux 内核(Kernel)。如果按照狭义操作系统的定义,Linux内核本身就是操作系统的核心部分,负责管理计算机最重要的资源,例如进程调度、内存管理、文件系统以及硬件驱动等。它就像一座建筑的地基,虽然用户平时看不到,但整个系统都建立在它之上。

而安卓(Android)则是在Linux 内核的基础上进一步扩展而来的广义操作系统。它不仅包含Linux 内核,还加入了大量系统组件,例如运行环境、原生库、系统服务以及开发接口等,为应用程序开发提供了完整的平台。

在安卓之上,各大手机厂商又会根据自身需求进行深度定制,加入自己的功能、界面设计以及生态服务,形成用户最终接触到的手机系统。例如:

  • OPPO使用的是ColorOS
  • 小米使用的是HyperOS
  • 华为使用的是HarmonyOS(部分版本与安卓生态兼容)。

这些系统虽然在界面和功能体验上各不相同,但很多传统智能手机系统的底层依然与安卓体系存在紧密联系,而安卓的底层核心则离不开Linux内核的支持。

简单总结:

Linux 内核负责管理底层资源,安卓负责构建完整移动操作平台,厂商系统负责在安卓基础上打造差异化体验。

三者并不是竞争关系,而是一层套一层的技术演进关系,共同组成了今天智能手机生态的基础架构。

三、操作系统的核心目标——管理资源与提供服务

理解操作系统之前,我们需要先明确一个核心问题:操作系统为什么存在?它到底想解决什么问题?简单来说,操作系统主要承担两个方向的任务:

  • 对下管理硬件资源,与硬件进行交互。
  • 对上为用户程序(应用程序)提供一个良好的运行环境。

其中,向下管理硬件是操作系统最核心的职责。计算机中的CPU、内存、磁盘、网卡等硬件资源,本身并不会主动协调工作,而操作系统需要负责统一调度和管理,让这些硬件能够高效、有序地运行。

而向上提供运行环境,则是操作系统为了方便用户和应用程序使用计算机资源。程序开发者不需要直接面对复杂的硬件细节,只需要通过操作系统提供的接口,就可以完成文件读写、内存申请、网络通信等操作。

这两个目标都可以看作操作系统存在的意义,但如果深入理解:

管理硬件资源是操作系统最终目的,而为应用程序提供良好环境,是实现这一目的的重要手段。

3.1 软硬件体系的层次化结构
3.1.1 什么是软硬件层状结构?

为了实现操作系统的目标,计算机系统并不是简单地将所有功能堆积在一起,而是设计了一套非常巧妙的软硬件层状结构(Layered Structure)

这种结构将整个计算机系统按照不同职责划分为多个层次:用户应用程序——系统程序(Shell、函数库等)——操作系统内核(Kernel)——计算机硬件,每一层只负责自己的工作,并通过规定好的接口与下一层进行交互。这种设计思想非常接近软件工程中的两个重要原则:

  • 高内聚:让功能相似、职责相近的内容集中在一起。
  • 低耦合:模块之间保持独立,通过接口进行连接,而不是相互依赖内部实现。

这种层次化设计带来的最大优势,就是系统更加容易维护和扩展。比如:

  • 磁盘损坏了,只需要更换磁盘;
  • 内存条出现问题,只需要替换内存;
  • 硬件升级,也不会影响上层应用程序运行。

底层硬件的变化,被操作系统这一层很好地隔离开来。复杂的硬件,被操作系统封装成简单统一的服务;复杂的系统,被层次结构拆解成清晰可管理的模块。

3.1.2 深入拆解软硬件交互流程

软硬件层状结构涉及的内容非常庞大,如果逐层展开,会牵扯到大量底层知识。所以这里我们不展开所有细节,而是通过一个简单案例,把这些层次串联起来。假设我们在程序中调用 C 标准库提供的printf函数,将一段文字输出到显示器。表面上看,我们只是调用了一个普通函数:

printf("hello Linux\n");

但实际上,这条指令背后经历了一系列层次转换:printf并不是直接操作显示器,而是对底层操作进行了封装,它内部会进一步调用操作系统提供的系统调用接口。随后,系统调用进入操作系统内核,由内核负责处理具体的资源请求。操作系统内核会调用对应的驱动程序,让驱动程序与硬件设备进行通信。最终,驱动程序控制显示设备,将字符真正显示到屏幕上。整个过程可以简单理解为:

printf(用户程序) → 系统调用 → 操作系统内核 → 驱动程序 → 硬件设备

好,看完这个流程,你可能还是有点懵:“一个简单的打印,为什么要绕这么多层?”别急,下面我们就逐个拆开,看看每一层到底负责什么。

3.1.2.1 系统调用——用户访问内核的唯一通道

什么是系统调用?

系统调用(System Call),简单来说,就是操作系统内核提供给上层应用程序使用的接口。应用程序运行在用户空间,无法直接访问操作系统管理的核心资源,例如 CPU、内存、硬盘以及各种硬件设备。应用程序想要请求操作系统完成某些任务,就必须通过系统调用进入内核空间。系统调用是用户空间进入内核空间的唯一合法通道。

常见的系统调用:

  • 1. 进程控制:负责管理程序的运行状态。
    • fork:创建新的进程
    • exit:终止进程
  • 2. 文件操作:负责对文件进行访问。
    • open:打开文件
    • read:读取文件
    • write:写入文件
    • close:关闭文件
  • 3. 设备管理:负责控制硬件设备

    • ioctl:设备控制
    • read/write:设备数据读写
  • 4. 内存管理:负责申请和管理内存资源。
    • brk:调整进程数据段大小,申请内存
    • mmap:建立内存映射

为什么需要系统调用?

系统调用的存在,是为了降低耦合度、保证系统安全,同时为应用程序提供统一的服务接口。

如果应用程序可以直接操作硬件,会发生什么?我们来看一个生活中的例子。

操作系统就像一家大型银行。银行内部存放着大量现金,而这些现金就相当于计算机中的核心资源:

  • 内存资源;
  • CPU 调度权;
  • 硬件访问权限。

而用户程序,就像来到银行办理业务的客户。银行不会因为客户需要钱,就允许客户直接进入金库。如果任何客户都可以自由打开保险柜:

  • 资金安全无法保障;
  • 银行秩序彻底混乱;
  • 整个系统最终崩溃。

同样,操作系统不信任任何人,但必须为你服务,操作系统也不会允许任何应用程序直接访问硬件资源。因为程序可能存在:

  • 权限不足;
  • 编写错误;
  • 恶意操作。

于是,银行设置了一个防弹玻璃窗口。客户只能站在窗口外,通过窗口向柜员提交业务申请。这个窗口,就对应计算机中的:系统调用接口,用户程序提出请求,并传递必要参数:

  • “我要打开这个文件。”
  • “我要申请一块内存。”
  • “我要向屏幕输出一段文字。”

内核负责执行,应用程序只负责请求,然后由操作系统内核中的工作人员负责处理。柜员收到请求后,会先检查客户身份:

  • 是否拥有权限?
  • 请求是否合法?
  • 资源是否满足?

确认无误后,柜员才会进入金库取出现金,再通过窗口交给客户。对应到计算机中:

  • 应用程序发起系统调用;
  • 内核检查权限;
  • 内核访问硬件资源;
  • 返回执行结果。

整个过程中,应用程序始终无法直接接触底层资源。所以,系统调用本质上就是操作系统设计的一道安全边界:它既限制了应用程序对硬件的直接访问,又为应用程序提供了使用系统资源的能力。这也是现代操作系统能够做到安全、稳定、高效运行的重要原因。

在实际开发过程中,我们很少会直接编写系统调用。原因很简单:系统调用虽然功能强大,但使用起来比较底层,需要开发者直接处理参数传递、错误返回以及系统资源交互等细节。

日常编程中我们更多使用的是库函数,例如C语言中的printf、scanf等。

库函数可以理解为银行提供的“自助服务设备”。用户不需要亲自填写复杂的业务申请,只需要按照设备提示操作即可,而背后的流程仍然由银行内部完成。

库函数负责提供方便易用的接口,系统调用负责连接应用程序与操作系统内核。(通常情况下,只要一个库函数涉及硬件资源访问,那么它底层大概率都会封装系统调用。)

操作系统为了保护自身的稳定运行,必须始终保持在幕后。它不会允许应用程序直接接触硬件,而是通过系统调用这一扇“安全窗口”与外界交互。这种设计带来了两个重要优势:

  • 安全性:避免用户程序随意操作硬件,破坏系统资源;
  • 稳定性:屏蔽底层硬件差异,让应用程序无需关心硬件实现细节。
3.1.2.2 驱动程序——连接内核与硬件的桥梁

什么是驱动程序?

驱动程序(Driver),简单来说,就是连接操作系统与硬件设备之间的桥梁。它位于操作系统和硬件之间,负责将操作系统发出的通用指令,转换成硬件能够理解的具体操作。可以把驱动程序理解为一个“翻译官”:

  • 操作系统只需要告诉驱动程序:“我要读取数据。”
  • 驱动程序负责翻译成对应硬件能够执行的操作。
  • 硬件完成任务后,再由驱动程序将结果反馈给操作系统。

通过驱动程序,操作系统无需了解每一个硬件内部的实现细节,就能够统一管理各种设备。

为什么需要驱动程序?

计算机中的硬件种类非常庞大,而且不同厂商生产的设备都有自己的工作方式。

  • 不同品牌的显卡,有不同的控制方式;
  • 不同型号的硬盘,有不同的数据交互协议;
  • 不同厂商的打印机,也有不同的通信方式。

如果操作系统需要为每一种硬件单独编写控制逻辑,那么整个系统会变得极其复杂。因此,操作系统采用了驱动程序这一层抽象:

硬件差异交给驱动处理,操作系统只面对统一接口。

这样既降低了系统复杂度,也提高了硬件扩展能力。

驱动程序种类非常多,因为几乎每一种硬件设备都需要对应的驱动支持。

  • 网络设备驱动:负责网络设备与操作系统之间的数据交互——网卡驱动
  • 存储设备驱动:负责管理存储设备的数据访问——磁盘控制器驱动、NVMe驱动
  • 输入输出设备驱动:负责处理用户输入以及设备输出——显卡驱动、键盘鼠标驱动、打印机驱动
  • 总线驱动:负责管理设备与计算机之间的连接方式——USB驱动、PCIe驱动

在软硬件层状结构中:

系统调用负责让应用程序进入操作系统,驱动程序负责让操作系统控制硬件。

3.2 总结——软硬件体系结构中的调用链路

OK,回过头来,我们把刚才整条链路重新梳理一下:

  • 库函数可能在底层封装了系统调用,让程序员不需要直接面对复杂的底层接口。
  • 访问操作系统资源,必须通过系统调用。它本质上也是一种函数,只不过这个函数不是由用户编写,而是由操作系统提供。
  • 我们的程序只要涉及硬件访问,就必须穿过整个软硬件层状结构。从应用程序、库函数、系统调用、操作系统内核、驱动程序,最终到达硬件设备。

再回到刚才那张图,其实其中连接用户程序与操作系统内核的这一层,就是系统调用接口。

它像一座桥梁,将上层应用与底层资源连接起来:既隐藏了复杂的硬件细节,又保证了系统运行的安全与稳定。

看到这里,是不是对整个软硬件体系结构有了一个更加清晰的认识?

四、操作系统的管理哲学:先描述,再组织

在整个计算机软硬件体系中,操作系统扮演的角色其实非常明确它本质上是一款负责“管理”的软件。但问题来了:操作系统到底是如何管理计算机中成千上万个资源的?难道操作系统真的需要像管理员一样,一个个认识硬件、一个个了解程序吗?当然不是。操作系统采用了一种非常经典的思想:先描述,再组织。也就是说,操作系统并不会直接管理一个复杂的实体,而是先通过数据结构对它进行抽象描述,再通过组织这些描述信息,实现高效管理。还是用一个例子来理解。

4.1 第一阶段:建立管理模型——从实体到数据

假设有一所规模庞大的学校,校长就是管理者,而成千上万名学生就是被管理对象。很显然,校长不可能每天亲自和每一个学生见面,更不可能记住每个人的所有信息。那么校长如何了解并管理这些学生呢?答案是:建立一份学生信息表。表格里记录了每个人的姓名、性别、年龄、籍贯、紧急联系人、各科成绩、职位、宿舍号等关键信息,有了这张表之后,校长管理学生,本质上就变成了:管理这张记录学生信息的数据表。学生本人不需要一直站在校长面前,校长也不需要直接接触每个人,只需要操作和维护这份数据记录,就能够完成管理。但是,当学生数量从几百增长到几万时,新的问题出现了。如果校长想找:

  • 某个成绩异常的学生;
  • 某个班级的平均成绩;
  • 某个地区学生数量;

如果只是依靠一张巨大的表格,从第一行开始慢慢查找,无疑会非常低效。这就引出了管理中的第二个问题:不仅需要描述对象,还需要合理组织这些描述信息。而这,正是操作系统管理思想的核心。在 Linux 中:

  • 学生 ≈ 进程、文件、硬件资源等被管理对象;
  • 学生信息表 ≈ 数据结构(PCB、文件结构体等描述信息);
  • 校长管理学生 ≈ 操作系统管理资源。

操作系统并不是直接“管理”资源本身,而是通过描述对象 + 组织对象,最终实现对整个计算机系统的高效管理。

4.2 第二阶段:抽象对象模型——通过结构体完成描述

为了解决第一阶段中信息管理效率低的问题,校长(此时已经化身为一名优秀的程序员)决定不再依赖那张庞大而混乱的信息表。他开始思考:既然每个学生都有姓名、年龄、成绩等共同属性,那么能不能先定义一个统一的模板?于是,他利用C++中结构体(struct)或类(class)的思想,设计出了一个学生模型:

struct Student
{
    string name;    // 姓名
    char sex;       // 性别
    int age;        // 年龄
    float score;    // 成绩
    string origin;  // 籍贯
    // ... 其他属性
};

通过这个结构体,校长不需要再单独记录每一个学生的信息,而是先定义出一个统一的“学生模板”。之后,每一个真实存在的学生,都可以按照这个模板,在计算机中被表示成一个具体的对象。比如:

  • 张三 → 一个 Student 对象
  • 李四 → 一个 Student 对象
  • 王五 → 一个 Student 对象

他们虽然是不同的人,但都拥有相同的数据结构。这一步,就是操作系统管理思想中的第一步:先描述。所谓“描述”,就是将现实世界中的管理对象进行抽象,把它们共有的属性提取出来,形成计算机能够理解的数据结构。在操作系统中也是如此:

  • 一个进程不会直接被操作系统“盯着管理”;
  • 一个文件不会直接被操作系统“面对面操作”;
  • 一个硬件设备也不会以原始形态存在。

操作系统会为它们创建对应的描述信息:

  • 进程 → PCB(进程控制块)
  • 文件 → 文件结构体
  • 硬件 → 设备信息结构

先把对象“数字化”,再进行后续管理。这就是:

先描述,再组织。

4.3 第三阶段:组织数据模型——通过数据结构实现管理

有了描述对象的模板之后,校长接下来面临新的问题:

学生的信息虽然已经被抽象成了一个个对象,但这些对象现在是零散存在的,如何才能高效管理成千上万名学生?

于是,校长想到:既然计算机中可以通过指针建立对象之间的联系,那么就把这些学生对象“串”起来。他在结构体中增加了一个指针:

struct Student
{
    // 学生基本属性...

    struct Student* next;  // 指向下一个学生对象
};

通过next指针,每个学生对象都能找到下一个学生,最终形成一个完整的链表:

Student1 -> Student2 -> Student3 -> Student4 -> NULL

此时,所有学生对象不再是孤立存在,而是被统一组织到了一个数据结构中,如果新增学生:

  • 创建一个新的学生节点;
  • 将节点插入链表。

如果删除学生:

  • 找到对应节点;
  • 修改指针关系;
  • 将该节点移除。

管理过程就从“寻找一个个学生”,变成了“操作一套组织好的数据结构”。这就是:再组织。通过合理的数据结构,将已经描述好的对象按照一定规则组织起来,从而实现对大量对象的高效管理。

现在再看操作系统中的管理思想,其实也是完全一样的。操作系统(校长)管理计算机中的各种资源:

  • 进程;
  • 文件;
  • 硬件设备;
  • 内存空间。

它并不是直接面对这些真实实体进行管理,而是先进行抽象。

例如:

  • 进程 → 使用 task_struct 描述;
  • 文件 → 使用文件结构体描述;
  • 设备 → 使用对应的设备结构体描述。

这些结构体中保存了对象的各种信息:

  • 状态;
  • 属性;
  • 资源关系;
  • 控制信息。

然后,操作系统再通过各种数据结构进行组织:

  • 链表;
  • 树;
  • 哈希表;
  • 队列等。

最终实现对海量资源的管理。这就是操作系统最核心的管理哲学:

先描述(Describe),再组织(Organize)。

有些教材也会把这个过程称为:建模。先把现实世界中的复杂对象抽象成计算机可以理解的模型,再通过数据结构将这些模型组织起来。其实这个思想贯穿了整个计算机领域。如果学习过数据结构和面向对象编程,会发现它们本质上也是同一套思想:

  • 先描述 —— 抽象对象,定义属性和结构;
  • 再组织 —— 利用数据结构和算法管理这些对象。

这也是为什么:C++中有class和对象;STL中有各种容器;数据结构中研究链表、树、哈希表;算法中研究如何高效操作这些结构。

它们最终都在解决同一个问题:如何让计算机高效地认识、组织和管理现实世界中的复杂对象。

所以总结一下:操作系统对进程、文件、硬件等资源的管理,本质上都会转化为两个步骤:

① 描述:将管理对象的信息抽象出来,保存到对应的数据结构中。

例如:

进程 → task_struct
文件 → file_struct
设备 → device_struct

② 组织:利用链表、树等数据结构,将这些描述对象连接起来,再通过增删查改完成管理。

最终:

操作系统管理资源,本质上就是对各种数据结构的管理。

这就是“先描述,再组织”的核心思想。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐