从冯诺依曼体系结构到进程管理详解
从冯诺依曼体系结构出发,解析计算机硬件数据流动机制,阐述操作系统作为软硬件资源管理者的核心作用。重点介绍进程的概念定义、内核视角下的 PCB(进程控制块)及 Linux 下的 task_struct 结构体,并通过 ps、top 命令及 /proc 目录说明进程查看方法,帮助理解程序执行实例与系统资源调度的底层逻辑。

从冯诺依曼体系结构出发,解析计算机硬件数据流动机制,阐述操作系统作为软硬件资源管理者的核心作用。重点介绍进程的概念定义、内核视角下的 PCB(进程控制块)及 Linux 下的 task_struct 结构体,并通过 ps、top 命令及 /proc 目录说明进程查看方法,帮助理解程序执行实例与系统资源调度的底层逻辑。

计算机系统的运行离不开硬件与软件的密切配合,其中,冯·诺依曼体系结构为现代计算机硬件设计奠定了基础,而操作系统则是管理软硬件资源、为用户程序提供执行环境的核心软件。本文从**冯诺依曼体系结构 (计算机硬件组成) 和操作系统 (计算机不可或缺的软件)**出发,由浅入深带各位初识进程!
冯诺依曼体系结构由约翰·冯·诺依曼于1945年提出,是现代计算机系统普遍采用的一种结构模型。该模型由五个核心部分构成:
RAM),用于存储程序和数据ALU)与控制器(CU)目前为止,我们所能认识到的计算机,都是由一个个的硬件组成的,这些硬件被分成了以下几个单元:
关键特性:
在冯诺依曼体系中,最核心的思想是:程序和数据以相同方式存储于存储器中,并通过 CPU 顺序读取执行。
关于存储器,我们需要认识到:
\n时,是可能会被缓存起来的?会被缓存到哪里?
CPU 计算好的数据,返回到内存中,再传输到输出设备中;输入设备中的数据,先加载到内存中,再由 CPU 读取进行处理。内存本质就是一种硬件上的缓存。
CPU 在计算内存中的一些数据时,外设中的其他数据依然可以继续加载到内存中,等到 CPU 进行计算时,需要被计算的数据已经被全部加载进内存了,这样数据就完成了预加载,数据在硬件中的传递也就由串行变成了并行。所以说,内存是硬件级别的缓存空间。这个加载程序或数据的工作是由操作系统完成的。
CPU 通过地址访问它们。CPU 不会直接访问外设,所有设备都必须先与内存交互。不过,如果我们对冯诺依曼的理解倘若仅仅停留在概念上,是不够的。我们需要深入到对软件数据流理解上。下面我们以登上 QQ 开始和某位朋友发消息为例来体现下冯诺依曼结构体系中数据的流向。
假设你用 QQ 给朋友发文件,这个过程中背后的数据流大致如下:
ALU)对内存中的文件数据进行分块、加密和压缩。TCP/IP)封装数据包,添加协议头部信息(如 IP 地址、端口号)。DMA 传输到网卡(输出设备)**的发送缓冲区。关键硬件协作示意图
发送方:磁盘 → DMA → 内存 → CPU 处理 → 内存 → DMA → 网卡 → 网络
接收方:网络 → 网卡 → DMA → 内存 → CPU 处理 → 内存 → DMA → 磁盘
总结:在冯诺依曼体系中,所有外设读写都要经过内存。无论你是点击、输入、还是传输文件,实际的数据传输路径永远遵循'外设 ↔ 内存 ↔ CPU'。
操作系统(Operating System,简称 OS)是介于硬件与应用程序之间的管理软件,本文针对以下三个问题展开讨论:
操作系统是什么?
为什么需要操作系统管理软硬件?
操作系统如何实现软硬件管理?
bash、zsh,用于人机交互。glibc、libc 等,简化开发者使用系统调用的复杂性。总结:操作系统是一款进行管理的软件,这里的管理既包括硬件也包括软件。
在没有操作系统的年代,每一个程序都必须直接控制硬件,开发难度极高,效率低下。操作系统的引入使得:
一句话总结:操作系统是'硬件资源管理者 + 用户程序服务者'。
综合以上,我们就可以很好的回答我们为什么要有操作系统了。
操作系统通过管理好底层的软硬件资源==(手段),为用户提供一个良好(稳定、高效、安全)的执行环境(目的)
操作系统通过驱动程序,获取软硬件的相关数据和状态信息,来实现对软硬件的管理
C++ 中的类,C 语言 中的 struct)描述软硬件资源C 语言 来实现的。C++ 为例,C++ 是一门面向对象的语言,其中有类和 STL。
描述 一个对象STL 中的各种容器 (本质是数据结构),诸如 vector,list 等,可以将对象 组织 起来描述 和 组织 这两步之后,我们就可以很方便的进行管理了。
struct 结构体 把所有的资源信息描述出来,再通过链表或其他更高效的数据结构来组织软硬件资源,通过对数据结构的管理,实现对计算机软硬件资源的管理。组织起来后,对资源的管理,无非就是对这些数据结构的增删查改
总结核心方法:
操作系统首先用'结构体(struct)'来描述各种硬件或软件资源:
Linux 中:
task_struct 描述;file 结构体表示;device 结构体封装。fork()、read()、write())进入内核,完成实际资源操作。库函数和系统调用是上下级关系,库函数内封装了系统调用。
操作系统不相信任何人,系统调用是操作系统对用户暴露的接口,供给开发使用
操作系统是硬件的管理者,想要访问硬件,必须经过操作系统也就是系统调用在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
read()、write()、fork() 等;fopen()、printf(),以降低调用难度,促进二次开发。进程也是操作系统内的资源,同样遵从'先描述,再组织'的设计理念
CPU 只能从内存中读数据。电脑开机的过程,实际就是把操作系统加载到内存中的过程。
先说进程的定义,大多数教材中给出的进程的定义如下:
taskps ajx | grep myprocess 查看刚刚执行的进程。其中
ps ajx 列出系统所有的进程ps ajx | grep myprocess 将所有进程通过管道输入,过滤 myprocess 进程正在运行的程序,程序的一个执行实例,叫做进程
显而易见:
一个操作系统,不仅仅只能运行一个进程,是可以同时运行多个进程的!!!
因此
操作系统必须将这多个进程管理起来。如何管理呢?答案是先描述,再组织
首先,操作系统需要先认识进程!
思考?我们人是怎样认识一个事物或者对象的?
人是通过
描述事物的属性来辨识事物的,也就是面向对象的过程。当相关的属性积累的足够多时,这一堆属性的集合,就是目标对象。人类就是这么认识事物的。
那么操作系统认识进程,也需要足够多的进程的属性。由于操作系统是用 C 语言 写的,因此操作系统必然采用 struct 来描述进程的各个属性。
描述进程,要包含进程的属性的集合。结论如下:
属性 的 struct 对象,PCB。process ctrl blcok,进程控制块,是进程的属性的集合。struct 对象包含描述进程的所有属性,操作系统通过 PCB 进程控制块来辨识进程基于以上内容,我们可以得出操作系统内核观点下的进程的概念:
PCB 也不叫进程PCB 结构体对象 和 加载到内存中的程序的代码和数据 合起来 才叫进程PCB 由操作系统内部自己维护的,代码和数据是程序员自己写的。code 和 data 加载到内存,操作系统还根据操作系统内的 描述进程的进程控制块,为当前进程创建 PCB,把该进程的相关属性填充好,初始化,形成一个 PCB,该结构体是操作系统自己形成的PCB 对象做管理(增删查改等),就能管理好进程。对进程的管理,本质是对内核 PCB 数据结构对象的管理PCB 数据结构对象:包含描述这个进程的所有属性值PCB 结构体对象,操作系统内管理进程就变成了管理 PCB 结构体对象。操作系统内是用链表来组织 PCB 的,因此实现对进程的管理本质是对链表的增删查改以上 PCB 是所有操作系统进程的设计理念,不同的操作系统对 PCB 的实现不完全相同,我们来看Linux下具体是如何实现的。
进程所有的属性信息被放在一个叫做
进程控制块的数据结构中,可以理解为进程属性的集合。
一般称之为 PCB(process control block),Linux 操作系统下的具体的 PCB 是:task_struct
Linux 中描述进程的结构体叫做 task_structtask_struct 是 Linux 内核的一种数据结构,即一种数据类型(自定义类型),它会被装载到 RAM(内存) 里并且包含着进程的信息,这个装载的过程就是 task_struct 的实例化task_struct 是一种自定义数据类型,Linux 内核中,最基本的组织 task_struct 的方式,是采用双向链表组织的。
PCB 不只是双向链表内的一个结点
PCB 结点可能同时也属于某个二叉树或者队列中的结点PIDCPU 要调度多个进程,就注定了多个进程要竞争 CPU,因此需要设定进程的调度优先级Linux 内核中,最基本的组织进程
task_struct的方式,是采用双向链表组织的。但task_struct不是仅存在于双向链表中
task_struct是一个节点,可能既属于链表中,也同时处于队列或二叉树中
命令 1
命令:ps
功能:查看系统下的进程
常用选项:ajx,用于查看系统下的所有进程
ps 也是一个可执行程序,因此 ps 运行起来是一个进程,grep 过滤时,会过滤出所有含有 ps 的所有内容
ps ajx 和 grep ps 都含有 ps,因此都会高亮显示。ps ajx | head -1 && ps ajx | grep processName
head -1 用于显示第一行,显示进程表头信息,ps ajx | grep processName 用于指定过滤进程 precessName命令 2
命令:top
功能:查看系统 CPU 资源使用状态
常用选项:无
PID 就是进程的编号,由此达到查看进程的目的。进程的信息还可以通过
/proc系统目录查看每一个进程在系统运行期间,关掉后再重启,系统为进程重新分配的
PID大部分情况是不一样的
ls /proc 查看系统内所有的进程。/proc 目录是一个特殊的系统目录
/proc 目录是系统将内存中的数据,通过可视化的方式,以目录的形式向我们呈现PID查看当前进程的目录
PID 查看当前目录的内容:ls /proc/ 161157 -l,其中目录内有两个关键信息:
cwd:current working directory,表示当前进程的工作目录。exe:指向当前可执行程序的存储路径C 语言使用代码 fopen("log.txt", "w") 创建文件时,没有指定文件在哪里创建,为什么会在当前目录下创建文件?touch test.c 这个命令,一旦运行起来变成进程,我们的 touch 命令并没有指定路径,却会自动在当前目录下创建文件?cwd,current working directorycwd。调用 fopen 或 touch 或其他的命令时,用户传入的路径是 "log.txt",在系统层面,会默认把进程启动时记录的 cwd 路径拼接到 "log.txt" 前面。即 cwd/"log.txt"。cwd 就叫当前路径通过本文的探讨,我们从冯诺依曼体系结构出发,深入理解了计算机硬件的核心组成与数据流动的本质。无论是键盘输入、屏幕显示,还是网络通信与文件传输,所有操作都严格遵循 '外设 ↔ 内存 ↔ CPU' 的协作逻辑。这一设计不仅奠定了现代计算机的基石,更揭示了内存作为数据中转枢纽的核心地位。
在此基础上,我们认识到操作系统是连接硬件与软件的桥梁。它通过**'先描述,再组织'**的哲学,以数据结构(如 task_struct)描述资源属性,并通过系统调用与高效算法实现资源管理。这种设计思想在进程管理中体现得尤为明显:进程作为程序执行的实例,其本质是内核数据结构(PCB)与代码数据的结合体,操作系统通过管理 PCB 的链表或树等结构,完成对进程的调度、隔离与资源分配。
对于我们而言,理解进程的底层逻辑(如通过 /proc 目录查看进程信息、通过 ps 命令分析运行状态)是优化程序性能、排查问题的重要基础。而这一切的背后,始终贯穿着操作系统的核心使命——以安全、高效的方式,为程序提供执行环境。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online