【冯诺依曼体系结构 + 操作系统基本概述】目录
- 前言:
- ---------------冯诺依曼体系结构---------------
-
- [1. 什么是冯诺依曼体系结构?](#1. 什么是冯诺依曼体系结构?)
- [2. 程序在运行之前为什么要加载到内存中?](#2. 程序在运行之前为什么要加载到内存中?)
- [3. 冯诺依曼体系结构的局限?](#3. 冯诺依曼体系结构的局限?)
- [4. 如何通过冯诺依曼体系结构来理解数据流动?](#4. 如何通过冯诺依曼体系结构来理解数据流动?)
- ---------------操作系统概述---------------
-
- [1. 什么是操作系统?](#1. 什么是操作系统?)
- [2. 操作系统有哪些部分组成?](#2. 操作系统有哪些部分组成?)
- [3. 为什么需要操作系统?](#3. 为什么需要操作系统?)
- [4. 操作系统是如何进行管理的?](#4. 操作系统是如何进行管理的?)
- [5. 什么是系统调用和库函数?](#5. 什么是系统调用和库函数?)

往期《Linux系统编程》回顾:/------------ 入门基础 ------------/
【Linux的前世今生】
【Linux的环境搭建】
【Linux基础 理论+命令】(上)
【Linux基础 理论+命令】(下)
【权限管理】/------------ 开发工具 ------------/
【软件包管理器 + 代码编辑器】
【编译器 + 自动化构建器】
【版本控制器 + 调试器】
【实战:倒计时 + 进度条】
前言:
🎉hi~ 小伙伴们大家光棍节好啊,☆(・ω<)★✨
嗯~ o( ̄▽ ̄)o今天是双11哦,一个兼具 "单身社交" 与 "消费狂欢" 双重属性的节日,影响力覆盖全年龄段,太有氛围感啦~哈哈 (ノ≧∀≦)ノ💻🛒
经过之前的铺垫,咱们已经能熟练操作 Linux 操作系统,也摸清了 Linux 下的常用开发工具,还通过实战练了手 ------ 现在,终于要正式踏入《Linux 系统编程》的核心学习啦!在开启正题前,先给大家安排一份 "新手必看先导教程"------【冯诺依曼体系结构 + 操作系统基本概述】!
这俩内容是理解系统编程的 "底层逻辑钥匙",咱们简单说说重点:≧◉◡◉≦💡
冯诺依曼体系结构:是现代计算机的设计基础,明确了计算机五大核心部件组成,还规定了数据和指令的存储与运行方式,搞懂它就能明白程序在电脑里是怎么 "跑起来" 的 (・∀・)ノ゙操作系统基本概述:则会带大家认识 "系统管家" 的核心作用 ------ 它是硬件和应用软件之间的桥梁,负责管理硬件资源、调度程序运行、提供用户交互接口,咱们平时用 Linux 的各种操作,背后都是操作系统在默默 "打工"~ (`・ω・´)先把这两个基础知识点吃透,后续学习系统编程就能事半功倍,赶紧跟着鼠鼠一起解锁这份 "入门秘籍" 吧! (´。• ᵕ •。)
---------------冯诺依曼体系结构---------------
1. 什么是冯诺依曼体系结构?
冯・诺依曼体系结构:是 1945 年由美籍匈牙利数学家约翰・冯・诺依曼(John von Neumann)提出的 计算机硬件设计框架
- 它确立了现代计算机的核心结构逻辑,至今仍是绝大多数通用计算机(如:个人电脑、服务器)的设计基础
- 其核心是
"存储程序原理",即 "程序与数据以二进制形式共同存储在存储器中,计算机按顺序读取指令并执行",具体包含五大核心组件和三大基本特征
五大核心硬件组件
- 运算器(Arithmetic Logic Unit, ALU)
负责执行算术运算(如:加减乘除)和逻辑运算(如:与、或、非、比较),是计算机的 "计算核心"- 控制器(Control Unit, CU)
负责协调计算机各组件的工作:按顺序从存储器中读取指令、解析指令含义,再向运算器、存储器、输入/输出 设备发送控制信号,确保指令逐步执行(相当于计算机的 "指挥中心")- 存储器(Memory)
用于同时存储程序代码和数据(冯・诺依曼的核心设计之一),早期以磁芯存储器为主,现代则以内存(RAM)为代表。特点是 "按地址访问",即通过地址找到对应的存储单元,读取或写入二进制信息- 输入设备(Input Device)
负责将外部信息(如:用户操作、数据文件)传入计算机
- 例如:键盘、鼠标、话筒、摄像头、扫描仪、
网卡、磁盘- 输出设备(Output Device)
负责将计算机的处理结果反馈到外部
- 例如:显示器、打印机、音箱、
网卡、磁盘

关于冯・诺依曼体系结构,有几点关键内容需要强调:
- 这里所提及的存储器,指的是内存
- 在不考虑缓存的情况下,CPU 仅能对内存进行读写操作,无法直接对输入或输出设备等外设进行数据层面的访问
- 外设(输入或输出设备)若要进行数据的输入或输出,也只能向内存写入数据或者从内存中读取数据
简而言之 :所有设备都只能直接与内存进行数据交互
三大核心特征
- 程序与数据同源存储
程序(指令序列)和数据都以二进制形式存储在同一个存储器中,而非分开存储(区别于早期 "程序外存" 的设计),这让计算机可以灵活加载不同程序,实现通用计算- 指令执行的 "串行顺序性"
控制器按 "取指令→解析指令→执行指令→取下一条指令" 的顺序循环执行(称为 "指令周期"),默认情况下指令逐条串行处理(现代计算机通过多核、流水线等技术优化,但核心逻辑仍基于此)- 二进制编码
计算机内部所有信息(指令、数据、符号等)均以二进制(0 和 1)表示,这是因为电子元件(如:晶体管)的 "通/断" 状态天然适合二进制逻辑,便于硬件实现和信号传输
2. 程序在运行之前为什么要加载到内存中?
在冯・诺依曼体系结构下,软件运行有着明确的流程和规则:
软件(程序)在运行之前,是以文件形式存储在磁盘 等外存储设备中的。而要让程序运行起来,必须先将其从磁盘加载到内存中。
这一要求是由冯・诺依曼体系结构规定的,因为该体系结构下,CPU 无法直接从磁盘等外设获取程序指令和数据来执行。
1. CPU 与内存的交互核心:CPU 要获取指令、写入数据,都只能与内存进行交互。
- 也就是说,CPU 执行我们编写的代码、访问程序中使用的数据时,这些代码和数据必须事先存在于内存里
2. 外设与内存的协作:
- 当涉及到输入(Input)操作时,外部设备(如:键盘、鼠标、传感器等)不能直接将数据传递给 CPU,而是需要先把数据
"拷贝" 到内存中- 同样,输出操作时,数据也是从内存 "拷贝" 到外部输出设备(如:显示器、打印机等)
整体来看,数据在设备间的流转,是从一个设备 "拷贝" 到另一个设备的过程
3. 冯诺依曼体系结构的局限?
冯・诺依曼体系的核心瓶颈是 "冯・诺依曼瓶颈":
由于存储器与运算器之间的数据传输速度,远低于运算器的处理速度,导致计算机整体性能受限于 "数据传输带宽"
所以冯・诺依曼体系结构的整体效率,很大程度上
由设备之间 "拷贝" 数据的效率决定
- 因为数据在不同设备(如:磁盘到内存、内存到 CPU、内存到其他外设等)之间的传输速度,会直接影响程序执行的整体速度
- 如果 "拷贝" 效率低下,即便 CPU 运算能力很强,整个系统的运行也会受到制约,就像是木桶原理 ------ 木桶能装多少水,取决于最短的那块木板。哪怕 CPU 运算速度再快(如同木桶中较长的木板),但只要数据在内存、外设、CPU 之间的传输("拷贝")拖慢了节奏,整个系统的性能就会被这一环节限制,无法充分发挥 CPU 等高速组件的能力

为缓解这一问题,现代计算机在其基础上增加了
缓存(Cache)、多核处理器、并行计算架构等,但核心的 "存储程序 + 五大组件" 逻辑仍未改变,因此仍属于冯・诺依曼体系的延伸。

4. 如何通过冯诺依曼体系结构来理解数据流动?
要深入理解冯・诺依曼体系结构,不能仅停留在概念层面,而要结合实际软件的数据流动过程来分析。
以在 QQ 上和朋友聊天(发送消息)为例,详细解释数据的流动过程:
发送消息的数据流过程(以北京用户给南京用户发 "你好!" 为例)
输入阶段:消息录入与初步处理
- 用户在位于北京的电脑上,通过键盘输入 "你好!",此时,键盘作为输入设备,将用户的按键操作转化为电信号形式的数据,然后把这些数据传输到计算机的内存中(遵循冯・诺依曼体系 "数据需先进入内存" 的规则)
- 同时,QQ 软件本身也早已被加载到内存中运行,随时准备处理用户的输入操作
处理与传输阶段:数据的运算、封装与网络发送
- 计算机的 中央处理器(CPU) 从内存中读取 QQ 程序的指令以及刚输入的 "你好!" 消息数据,进行一系列运算和处理(比如:按照 QQ 程序的逻辑,对消息进行格式封装等)
- 处理完成后,CPU 控制将封装好的消息数据再次写入内存
- 接着,网卡作为输出设备(负责网络数据输出),从内存中读取这些消息数据,按照网络通信协议(如:TCP/IP)进一步封装成网络数据包,然后通过网络(如:互联网)发送出去,数据包会经过一系列网络设备中转,最终向南京方向传输
接收与显示阶段:数据的接收、解析与呈现
- 首先,位于南京的电脑的网卡作为输入设备,接收到来自网络的数据包后,将其传输到内存中
- 然后,CPU 从内存中读取数据包,按照 QQ 程序的逻辑进行解析,提取出 "你好!" 这条消息数据
- 最后,显示器作为输出设备,从内存中获取解析后的消息数据,将 "你好!" 显示在屏幕上,完成整个消息接收与展示的过程
---------------操作系统概述---------------
1. 什么是操作系统?
操作系统(Operating System,简称 OS):是 管理计算机硬件与软件资源的核心系统软件 ,也是计算机系统中所有其他软件运行的"基础平台"和"桥梁"
- 它介于计算机硬件(如:CPU、内存、磁盘)和用户(或应用程序,如:QQ、浏览器、Office)之间
- 它负责 协调硬件资源分配、管理软件运行逻辑,同时为用户提供便捷的交互接口,是计算机能够正常工作的 "灵魂",没有操作系统,你的电脑就是一堆行尸走肉的废铁
2. 操作系统有哪些部分组成?
概括来讲,操作系统主要由以下两部分组成:
- 内核 :它承担着核心的管理工作,具体包括:
- 进程管理(负责
调度和管理计算机中运行的程序进程)- 内存管理(对计算机的内存资源进行
分配与回收等操作)- 文件管理(
管理存储设备上的文件,如:创建、删除、读写文件等)- 驱动管理(为计算机硬件设备
提供驱动支持,使硬件能与系统正常交互)- 其他程序 :
- 函数库(为应用程序提供可调用的函数,助力程序实现各类功能)
- shell 程序(为用户提供与操作系统内核交互的命令行界面,方便用户输入指令操作计算机)

3. 为什么需要操作系统?
如果没有操作系统,用户要使用计算机必须 "直接与硬件对话"------ 比如:用二进制代码编写指令控制 CPU,手动管理内存地址,这对普通人来说几乎不可能。
操作系统相当于"管家":
- 对用户:提供简单的交互方式(点击图标、输入指令),无需了解硬件细节
- 对应用程序:提供统一的接口,让软件无需适配不同硬件(比如:QQ 无需区分 "Intel CPU" 还是 "AMD CPU",只需调用操作系统的接口即可)
- 对硬件:合理分配资源,避免浪费(比如:CPU 不会因 "只运行一个小程序" 而闲置,内存不会因 "多个程序混乱占用" 而崩溃)
简单来说:操作系统就像计算机的 "管家":
- 既要,管好家里的 "硬件家具"(CPU、内存等)
- 又要,服务好 "软件客人"(应用程序)
- 还要,让 "主人"(用户)用得省心
没有它,计算机就是一堆无法协同工作的硬件零件。

小故事:国家的政府
一个生动的比喻:
操作系统就像是国家的政府
- 硬件(CPU、内存、硬盘) :
就像是国家的资源(土地、矿产、人力)- 应用程序(微信、Chrome浏览器、游戏) :
就像是国家的公司、学校、医院
政府做什么?
- 管理资源:政府决定土地给谁用,资金如何分配
- 提供公共服务:政府修建公路、提供电力、制定法律
- 协调与仲裁:如果两个公司争夺同一块地,政府来协调
没有政府,国家会陷入混乱;没有操作系统,计算机就无法工作
说白了操作系统就是一个:"管理者" 与 "协调者"
4. 操作系统是如何进行管理的?
一、"管理" 的核心逻辑(以 "校长管理学生" 类比)
要理解操作系统的 "管理",可以先看生活中的例子:校长(管理者)管理学生(被管理者),而辅导员负责执行校长的决策。
操作系统的 "管理" 也遵循类似逻辑,且有三个关键特点:
管理者与被管理者可 "不直接见面":
- 校长不需要逐个找学生沟通,就能完成管理
- 类似地,操作系统管理硬件、程序等 "被管对象" 时,也无需和它们 "直接交互"
"数据" 是管理的核心依据:
- 校长如何了解学生情况?靠 "Excel 表格" 里的学生数据(姓名、年龄、成绩等)
- 操作系统管理计算机资源(如:进程、内存、文件)时,也是通过 "数据结构" 记录资源的状态、属性,以此为依据做决策
"中间层" 负责数据传递:
- 校长不直接找学生要数据,而是由辅导员收集后汇报
- 操作系统里,硬件的状态、程序的信息也会通过 "驱动程序"、"系统接口" 等中间层,传递给操作系统的 "管理模块"
二、操作系统 "管理" 的技术映射:从 "Excel 表格" 到 "数据结构与算法"
生活中校长用 "Excel 表格" 管理学生,操作系统则用 "数据结构 + 算法" 实现对计算机资源的管理
以 "管理学生" 类比 "管理进程(运行的程序)" 为例:
"描述" 被管对象:
- 校长在 Excel 里用 "列" 定义学生的属性(姓名、年龄、成绩)
- 操作系统会用 结构体(如:struct stu) 定义进程的属性(进程 ID、内存占用、运行状态等)
cstruct stu { char name[20]; // 姓名 int age; // 年龄 float score; // 成绩 // 其他属性... struct stu *next; // 链表指针,用于组织多个学生 };"组织" 被管对象:
- 校长把学生的 Excel 行按 "班级"、"学号" 组织起来
- 操作系统会用 数据结构(如:链表、数组) 把进程的结构体 "串起来",形成 "进程链表"(如:
stu list),方便批量管理(新增、删除、查询进程)"操作" 被管对象:
- 校长对 Excel 里的学生数据做 "增删查改"
- 操作系统会用**算法**对进程链表执行同样的操作(比如:新增一个进程时,把它的结构体插入链表;查询进程时,遍历链表找对应结构体)
三、"先描述,再组织":操作系统的通用管理思路
无论是管理进程、内存,还是文件,操作系统都遵循
"先描述,再组织"的逻辑:
- 先描述:用 "结构体" 等方式,把被管对象的核心属性 "描述" 清楚(如:进程的 ID;内存占用;文件的路径、大小、权限)
- 再组织:用 "链表"、"哈希表" 等数据结构,把这些 "描述好的对象" 组织起来,形成可高效操作的 "资源集合"
这种思路能对任何 "管理场景" 进行建模(小到管理进程,大到管理分布式系统资源)
大家可以回想一下:很多面向对象编程语言中,是不是都有 "类" 和 "容器" 这两个核心概念?
只是不同语言的命名或具体实现略有差异 ------ 比如:
- C++ 里的容器归属于 STL(标准模板库)
- Java 中的容器是 Collections 框架 (如:
ArrayList、HashMap等)- Python 里则直接提供了 内置容器类型 (如:列表
list、字典dict、集合set等)
而这两个概念的设计逻辑,恰好对应了我们之前提到的 "先描述、再组织" 思想:
- 类(Class)的本质是 "先描述":通过定义类的成员变量(属性)和成员方法(行为),精准描述一类事物的特征与能力
- 容器(Container)的本质是 "再组织":当我们用类创建出多个对象(如:多个 "学生" 实例)后,容器负责将这些分散的对象按特定规则(如:顺序、键值映射)组织起来,方便后续的增删查改操作
可以说,面向对象语言中 "类 + 容器" 的组合,正是 "先描述、再组织" 这一管理思想在编程语言层面的经典体现。
简单来说 :操作系统的 "管理",就是用 "数据结构描述资源,用算法操作资源,用中间层传递资源信息",最终实现对计算机软硬件的高效管控 ------ 就像校长用 Excel + 辅导员,实现对学生的有序管理一样。

5. 什么是系统调用和库函数?
要理解系统调用 和库函数,核心是抓住它们在 "用户程序与操作系统交互" 中的不同定位:
- 系统调用是操作系统对外开放的
"底层入口"- 库函数则是对系统调用(或基础功能)的
"上层封装工具"
系统调用(System Call):操作系统的 "官方接口"
- 定义:系统调用是操作系统内核为用户程序(或其他系统程序)提供的 底层服务接口 ,是用户空间程序请求内核空间服务的唯一合法途径
- 简单说:操作系统内核掌握着计算机的核心资源(如:CPU、内存、硬盘、网络卡),普通用户程序没有权限直接操作这些 硬件/资源,只能通过 "系统调用" 向内核 "申请帮忙"
- 本质:"用户态" 与 "内核态" 切换的 "桥梁"
- 计算机运行时分为用户态 (普通程序运行的空间,权限低)和内核态(操作系统内核运行的空间,权限高)
- 当用户程序执行系统调用时,会触发 "态切换"------ 从用户态进入内核态,让内核代完成高权限操作(如:读写硬盘、分配内存),操作完成后再切回用户态
库函数(Library Function):程序员的 "便捷工具包"
- 定义:库函数是编程语言或第三方库提供的 预制函数集合 ,封装了常用的功能逻辑,供程序员直接调用以简化开发,无需重复编写底层代码
- 简单说 :库函数就像 "现成的工具"------ 比如:要计算平方根,不用自己写迭代算法,直接调用 C 语言标准库的
sqrt();要打印内容,不用自己处理显示器硬件,直接调用printf()- 本质:"对基础功能的封装",封装的内容分两种情况:
- 基于系统调用封装:大部分与 "系统资源交互" 的库函数,底层其实是调用了系统调用。
- C 语言的
printf(),底层会调用write()系统调用来向终端输出内容fopen()底层会调用open()系统调用来打开文件- 纯用户态逻辑封装:部分不涉及系统资源的库函数,底层没有调用系统调用,只是纯用户态的逻辑实现。
- C 语言的
strlen()(计算字符串长度)、memcpy()(内存拷贝)、sqrt()(平方根计算)------ 这些功能只需要操作用户态的内存数据,不需要内核帮忙。
一句话概括:
系统调用:是应用程序向操作系统内核请求服务的唯一正式通道
- 它是用户态进入内核态的"大门"
- 从开发视角来看,操作系统对外呈现为一个完整的整体,但会开放部分接口供上层开发使用,这些由操作系统提供的接口就是系统调用
库函数:是预先编写好、可供程序员直接调用的代码集合
- 它们可能藏在"用户态",也可能通过"大门"去请求操作系统服务
- 系统调用在功能上较为基础,并且对使用者的要求相对较高。所以,有心的开发者对部分系统调用进行适度封装,进而形成库函数------有了库函数,更上层的用户或者开发者开展二次开发就会便利很多
小故事1:去餐厅吃饭
想象
你(应用程序)去一家很高端的餐厅吃饭,后厨重地(内核空间),顾客不能进入。
- 系统调用:就像是按呼叫铃
- 这个动作本身是一个明确的、规定好的
请求(按铃)。厨师(操作系统内核)听到后,会从后厨(内核态 )来到你的餐桌前(用户态)为你服务- 你只能通过这种方式和后厨互动,不能自己跑进去。餐厅提供了菜单上所有可能的服务(比如:蒸羊羔、蒸熊掌、蒸鹿尾儿),但这些服务必须由他来完成
- 库函数:就像是餐厅里的服务员
- 有些菜 不需要惊动后厨,
服务员(库函数)在餐桌旁就能完成。比如:给你倒一杯水、拿一包纸巾
- 这相当于一个库函数完全在用户空间 自己就完成了工作(例如:C语言标准库中的
strlen函数计算字符串长度,它只是操作内存,不需要操作系统帮忙)- 但大部分菜 需要
服务员(库函数)将需求传达至后厨(内核空间),由厨师(操作系统内核)亲自完成。比如:做一道牛排,服务员(库函数)接到你的点单(调用)后,必须替你按铃(发起系统调用),把需求传递给厨师(操作系统内核)。后厨做好后,再由服务员端给你
小故事2:去银行取钱
想象
你(应用程序)去一家银行取钱,金库(内核空间),客户不能进入。
进入银行 (运行程序)
你走进了宽敞明亮的
银行大厅(用户空间),这里有很多其它客户(其他程序)在办理业务寻找帮助 (调用库函数)
你不知道具体该怎么取钱,于是你找到了
银行柜台(库函数)。柜台提供了很多标准化的服务:
- 简单服务 :比如咨询汇率、要一张存款单。这些服务柜台自己就能办,不用惊动后面
- 取钱申请 :但取钱这件事,柜台办不了。不过热情的
柜员(库函数)帮你填好了取款单 (格式化参数),上面写清楚了"账号XXX,取款500元"提交申请 (发起请求)
你现在有两个选择:
- A. 直接去找授权柜员 :你拿着填好的单子,直接去找那位有权限进金库的
高级柜员(系统调用)- B. 通过大堂经理 :或者,你先把单子交给
大堂经理 (Shell/命令行或图形界面)。经理一看是取款业务,就会帮你叫号 ,然后引导你去对应的高级柜员(系统调用)窗口核心业务办理 (执行系统调用)
高级柜员(系统调用)是唯一连接大厅和金库的通道。他收到你的单子(输入参数)后:
- 转身进入
金库重地(内核态)- 在金库里,他需要请示
行长(操作系统内核的核心代码),并按照行长立下的严格规矩(系统)来操作:核对身份、查账本、数钱、记账- 所有这些操作,你都看不见也管不着,完全由银行内部完成
返回结果 (系统调用返回)
高级柜员拿着现金和一张新的账目回单(返回值 ),从金库出来,回到窗口(返回用户态),把东西交给你
业务完成 (函数返回)
你拿到了钱,整个取款业务圆满完成。你可以选择就此离开,也可以继续让大厅的普通柜员 (库函数) 帮你办点别的,比如:把取出来的钱再重新存进去,哈哈😂
