linux系统复习:从冯·诺依曼到操作系统:一切的开场

一、冯·诺依曼体系:所有设备都只能和内存打交道

我们常见的笔记本、不常见的服务器,绝大多数都遵守冯·诺依曼体系结构。它把计算机拆成五类部件:

部件 举例 职责
输入单元 键盘、鼠标、扫描仪、手写板 把外界信息送进机器
输出单元 显示器、打印机 把结果送出机器
中央处理器 CPU 运算器 + 控制器 执行指令、做运算、发号施令
存储器 内存(注意:不是硬盘) 存放正在运行的程序和数据
(外存)硬盘 磁盘 长期保存,不直接参与运算

画成图大概是这样:

复制代码
              ┌─────────────┐
   输入设备 →  │             │  → 输出设备
  (键盘/鼠标) │    内  存    │  (显示器/打印机)
              │             │
              └──────┬──────┘
                     │ 总线
              ┌──────┴──────┐
              │     CPU     │
              │ 运算器+控制器 │
              └─────────────┘

三条必须记住的"硬规矩"

  1. 这里的存储器指内存,不是硬盘。 硬盘是外存,它要参与运算,必须先把数据搬进内存。

  2. CPU 只能对内存读写,不能直接访问外设。 不考虑缓存的前提下,CPU 的数据来源和去向只有内存一个。CPU 要"读键盘",实际上是键盘先把数据写进内存,CPU 再从内存读。

  3. 外设也只能和内存打交道。 键盘输入 → 写内存;显示器输出 → 从内存读。它不会绕过内存直接和 CPU 对话。

一句话总结:

内存是整台机器的"中转站",任何两个部件想交换数据,都得经过内存。

为什么非要这么设计?

因为速度差得太离谱:

部件 大致速度
CPU 一次运算 纳秒级(0.x ns)
内存一次访问 几十纳秒
硬盘一次随机读 毫秒级(比内存慢几十万倍)
键盘/网络 毫秒到秒级,且人类输入更慢

如果让 CPU 直接等硬盘、等键盘,CPU 99.99% 的时间都在发呆。所以设计上让内存做缓冲区:慢设备把数据攒到内存里,CPU 一口气从内存搬走;CPU 算完先写内存,慢设备再去慢慢取。这样"慢"被内存吸收掉了。

📌 这也解释了一个常见现象:程序"卡"的时候,往往不是 CPU 慢,而是在等 IO (等磁盘、等网络)。这就是后面进程状态里 S(睡眠)和 D(不可中断睡眠)的由来。


二、把"数据流动"讲透:QQ 发一条消息经历了什么

课件里有一道经典思考题:从你登录 QQ,给朋友发一条消息,到他收到,数据是怎么流动的?如果是发文件呢?

很多人能背"输入→CPU→输出",但说不清细节。我们一步步拆。

场景 1:发一条文字消息

你的电脑这侧:

  1. 你敲键盘,键盘控制器把按键扫描码写进内存中的输入缓冲区;
  2. CPU 从内存读到按键,交给 QQ 进程处理,你在聊天框里看到的字,是 CPU 把字符写回内存,显卡再从内存读出来画到屏幕上;
  3. 你点"发送",QQ 进程把这段文字组装成网络数据包,写进内存;
  4. 网卡(也是一种外设)从内存里把数据包读走,通过网线/无线发出去。

对方的电脑这侧:

  1. 对方的网卡收到数据包,写进内存;
  2. 网卡发中断通知 CPU:"有数据了";
  3. CPU 从内存取出数据,交给对方的 QQ 进程解析,再把文字写进内存;
  4. 对方的显卡从内存读数据,显示到屏幕上。

注意每一步:CPU 只碰内存,网卡只碰内存,显卡只碰内存。它们之间从不直接握手。

场景 2:发一个文件

差别在"数据从哪来":

  1. QQ 先从硬盘把文件读进内存(这一步是磁盘 DMA + 内核参与);
  2. 把文件切成分片、加协议头,仍放在内存里;
  3. 网卡从内存读走,发出去;
  4. 对方网卡写入内存 → CPU 处理 → 写入对方硬盘(落盘才算真的收到)。

所以发文件时你会看到磁盘和网络同时忙:磁盘 → 内存 → 网络,内存还是那个中转站。

📌 面试常问变体:"为什么大文件传输时内存占用会飙高?"------因为要经过内存缓冲;"为什么零拷贝技术能提速?"------因为它在想办法少搬几次内存。


三、操作系统:一个纯正的"搞管理"的软件

3.1 什么是操作系统

任何计算机系统都包含一个基础程序集合,称为操作系统(Operating System,OS)。笼统地说,它包括:

  • 内核(kernel):进程管理、内存管理、文件管理、驱动管理;
  • 其他程序:函数库、shell 程序等。

也就是说,OS ≠ 内核。我们平时说的"Linux",严格讲是内核 ;你敲命令用的 bash、链接用的 libc,是内核之外的"其他程序"。

3.2 设计 OS 的目的:两头讨好

复制代码
        ┌──────────────────────────────┐
        │        用户 / 应用程序          │
        └──────────────┬───────────────┘
                       │  对上:提供良好的执行环境
        ┌──────────────┴───────────────┐
        │           操作系统             │
        │   (纯正的"搞管理"的软件)        │
        └──────────────┬───────────────┘
                       │  对下:管理所有软硬件资源
        ┌──────────────┴───────────────┐
        │      硬件(CPU/内存/磁盘/网卡)   │
        └──────────────────────────────┘
  • 对下:与硬件交互,管理所有软硬件资源;
  • 对上:为用户程序提供一个良好的执行环境。

3.3 核心功能:管理

在整个软硬件架构里,操作系统的定位就是------一款纯正的"搞管理"的软件。

它不亲自算 1+1,也不亲自把字节写到磁盘磁道上。它做的事是:决定谁能用 CPU、用多久、用哪块内存、能不能打开这个文件。


四、如何理解"管理":先描述,再组织

这是整个操作系统课最重要的一句话,请务必吃透。

4.1 一个生活例子:学生、辅导员、校长

假设你是校长,要管理 2 万个学生。你会怎么做?

  1. 描述每个学生:姓名、学号、班级、成绩、奖惩记录......(存成一张表/一个结构体)
  2. 组织这些学生:按学院分组、按班级排队、按成绩排序......(用链表、数组、树)

校长从不直接接触学生 。他要"管理",只需要操作那两张东西:描述信息 + 组织结构。辅导员也是这么干的。

4.2 操作系统管硬件,同理

  • 描述 :给每个硬件/被管理对象定义一个 struct,把所有属性塞进去;

  • 组织 :用链表(或其他高效数据结构)把这些 struct 串起来。

    计算机管理硬件的套路:
    1. 描述起来 ------ 用 struct 结构体
    2. 组织起来 ------ 用链表或其他高效的数据结构

📌 记住这个套路,后面看到的一切都顺了:

被管理对象 描述它的结构体 怎么组织
进程 task_struct(PCB) 双链表串在内核里
虚拟内存区域 vm_area_struct 单链表 / 红黑树
打开的文件 struct file 文件描述符表
文件系统 struct super_block 等 VFS 树

所以"管理进程"= 用一个结构体描述进程 + 把结构体链起来。 这也直接回答了下一篇的问题:进程在操作系统眼里到底是什么?------一个 task_struct。


五、系统调用和库函数:OS 的"门面"

操作系统对外表现为一个整体,但它必须给上层留出口子,否则应用程序什么也干不了。

5.1 系统调用(system call)

操作系统提供的接口 ,叫做系统调用。比如:fork、execve、wait4、open、read、write......

特点:

  • 功能比较基础(就是一次内核能力的直接暴露);
  • 使用门槛相对高(要自己处理参数、错误码、平台差异,甚至要写汇编/内联汇编触发软中断);
  • 是唯一能进入内核的合法通道。

5.2 库函数(library function)

有心的开发者对部分系统调用做了适度封装 ,形成库(最典型的就是 libc)。有了库,上层开发者就能更方便地二次开发。

比如:

你写的 背后其实是
printf write(系统调用)+ 用户态缓冲 + 格式化
malloc brk / mmap(系统调用)+ 用户态内存池
fopen/fread open/read(系统调用)+ 用户态 FILE 缓冲

分层的直观图:

复制代码
   你的程序
      │ 调用 printf / malloc / fopen      ← 库函数(用户态)
      ▼
     libc
      │ 调用 write / brk / open           ← 系统调用(陷入内核)
      ▼
   内核(特权态)
      │ 操作硬件寄存器、页表、磁盘
      ▼
    硬件

📌 为什么要有这一层?因为系统调用**太"素"**了:write(1, buf, n) 每次只写几个字节,一次一次调,性能极差;printf 在用户态攒够一块再一次性 write,快得多。这也是第 7 篇里 exit 和 _exit 行为不同的根本原因(一个会刷缓冲区,一个直接走)。


六、承上启下:操作系统怎么管进程?

到这里,套路已经很清楚了:

操作系统管理进程,也是三步: 1. 先把进程描述起来(PCB / task_struct); 2. 再把进程组织起来(双链表); 3. 然后在需要的时候,读写这些结构体的字段(调度、切换、销毁)。

下一篇我们就去内核里,把 task_struct 拆开看:它到底记了哪些东西?以及那个让所有初学者困惑的 fork()------为什么一个函数会有两个返回值?


本篇小结

  • 冯·诺依曼体系下,所有设备只和内存打交道,内存是数据中转站;CPU 不能直接访问外设。
  • 操作系统 = 内核 + 其他程序(函数库、shell);核心定位是管理。
  • 管理的本质:先描述(struct),再组织(数据结构)。
  • 系统调用是 OS 暴露的基础接口,库函数是对它的封装;这是"用户态 / 内核态"分层的由来。
  • 进程管理的答案,就藏在 task_struct 这个结构体里。
相关推荐
程序员-Benothing1 小时前
SSH从入门到精通:密钥登录、config配置、跳板机
linux·运维·服务器·ssh
一条泥憨鱼1 小时前
【计算机网络】| 从 MAC 到 NAT 的跨网段通信全链路
服务器·网络·学习·计算机网络·macos
Elastic 中国社区官方博客1 小时前
Jina AI:Elasticsearch 集成
大数据·运维·人工智能·elasticsearch·搜索引擎·全文检索·jina
H.莓飛1 小时前
【Linux】自主 Shell
linux·运维·服务器·c语言·开发语言·visual studio
bigcarp1 小时前
Frida-dexdump 绕过app的Root检测
linux·运维·服务器
ggaofeng1 小时前
linux中的绿色版内存mysql
linux·运维·mysql
Lsetea1 小时前
curl访问HTTPS报28 Operation timed out:连接超时与总超时分层排查
运维·https·ssl证书·curl·tls
草莓熊Lotso2 小时前
【C++ 基于微服务的即时通讯系统】Elasticsearch 从安装到 C++ 客户端二次封装全落地
linux·网络·数据库·c++·elasticsearch·微服务
曦夜日长2 小时前
主从 Reactor 高并发服务器实战 (一):前置知识与功能目标
运维·服务器