前言:欢迎 各位光临 本博客,这里小编带你直接手撕Make/Makefile (自动化构建) ,文章并不复杂,愿诸君耐其心性,忘却杂尘,道有所长!!!!
**🔥个人主页:IF'Maxue-CSDN博客
🎬作者简介:C++研发方向学习者
📖个人专栏:
《C语言》
《C++深度学习》
《Linux》
《数据结构》
《数学建模》
⭐️人生格言:生活是默默的坚持,毅力是永久的享受。不破不立,远方请直行!
文章目录
-
- 一、冯诺依曼体系:电脑的"底层工作规则"
-
- [1. 程序没运行时,藏在哪儿?](#1. 程序没运行时,藏在哪儿?)
- [2. "加载"就是挪食材的过程](#2. “加载”就是挪食材的过程)
- [3. 存储分级:快的放近处,慢的放远处](#3. 存储分级:快的放近处,慢的放远处)
- [4. 两台电脑传文件,本质是啥?](#4. 两台电脑传文件,本质是啥?)
- 二、操作系统:电脑的"全能管家"
-
- [1. 操作系统由两部分组成](#1. 操作系统由两部分组成)
- [2. 管家怎么"管理"?核心是"先描述,再组织"](#2. 管家怎么“管理”?核心是“先描述,再组织”)
- 三、系统调用:和"管家"沟通的唯一通道
-
- [1. 系统调用像银行的"柜台"](#1. 系统调用像银行的“柜台”)
- [2. 库函数和系统调用的关系](#2. 库函数和系统调用的关系)
- 四、进程:正在"干活"的程序
-
- [1. 进程的"身份证":task_struct(PCB)](#1. 进程的“身份证”:task_struct(PCB))
- [2. 怎么查看进程?两种常用方法](#2. 怎么查看进程?两种常用方法)
- [3. 进程的"父子关系":所有进程都有爹](#3. 进程的“父子关系”:所有进程都有爹)
- [4. 用代码创建子进程:fork函数](#4. 用代码创建子进程:fork函数)
- 最后总结
一、冯诺依曼体系:电脑的"底层工作规则"
咱们先从最基础的说起------冯诺依曼体系,这其实就是电脑的"做事逻辑",核心是所有硬件都围着"运算器"转,就像大家都听主厨的指挥一样。

1. 程序没运行时,藏在哪儿?
你双击一个软件(比如QQ)前,它其实待在磁盘里(就是你电脑的C盘、D盘这类存储盘)。为啥不能直接在磁盘上跑?看下面这张图就懂了:

电脑有个死规矩:运算器只和内存打交道,键盘、磁盘这些外设也只跟内存交互。就像主厨(运算器)只用操作台上(内存)的食材,不会直接从冰箱(磁盘)拿------所以得先把"食材"(程序)从冰箱挪到操作台。
2. "加载"就是挪食材的过程
"加载"说直白点,就是把磁盘里的程序,拷贝到内存里。看这两张图,就是加载的完整流程:
加载完之后,运算器才能从内存里读指令、跑程序------这就是软件能运行的前提。
3. 存储分级:快的放近处,慢的放远处
电脑的存储不是一块铁板,而是分"快慢档"的,就像你把常用的东西放口袋,不常用的放柜子:

- 最快:CPU缓存(口袋,随手拿)
- 中等:内存(桌面,伸手够)
- 最慢:磁盘(柜子,要起身开)
这里还有个"木桶原理":程序跑多快,不看最快的硬件,只看最慢的那步。比如从磁盘拷到内存要1秒,哪怕运算器1毫秒能算完,整体还是得等1秒------所以效率由拷贝速度决定:
4. 两台电脑传文件,本质是啥?
你给朋友发个照片,看似简单,其实是"两台冯诺依曼机器互相传食材":本地磁盘→本地内存→网络→对方内存→对方磁盘。看这几张图,流程一目了然:
一句话总结:传文件就是"跨电脑的拷贝"。
二、操作系统:电脑的"全能管家"
有了硬件和底层规则,得有个"管家"来协调------这就是操作系统(OS),比如Windows、Linux、macOS。它的核心工作是管硬件、管软件,给你的程序提供舒服的运行环境。
1. 操作系统由两部分组成
管家也分"核心"和"助手":

- 内核:管家的核心,管最底层的事(比如分配内存、控制CPU)
- 其他程序:助手,比如图形界面(你电脑的桌面)、命令行工具
就连你的安卓手机,底层也是Linux内核------上面加了安卓的框架和APP,就像管家下面有专门管手机APP的助手:

2. 管家怎么"管理"?核心是"先描述,再组织"
不管管硬件还是程序,OS都遵循一个逻辑:先记清楚"对象是谁",再把它们"分组管理"。比如学校管学生:
- 先描述:记每个学生的姓名、学号、班级(用表格或表单记录)
- 再组织:按班级分组,方便查改
OS管硬件也一样,看这几张图:
比如管内存,先记录"内存块大小、是否被占用"(描述),再用链表把这些记录串起来(组织)------后续分配/回收内存,就是改这个链表,跟校长改学生表格一样简单:
一句话:世界上所有管理,都是先记清楚属性,再分组整理------OS也不例外。
三、系统调用:和"管家"沟通的唯一通道
管家很谨慎,不相信陌生人------你不能直接闯进它的"后台"(内核),只能通过它开的"窗口"(系统调用)办事。
1. 系统调用像银行的"柜台"
比如你去银行取钱,不能直接进金库,得通过柜台------系统调用就是OS的"柜台":

- 本质:OS提供的C函数(有输入参数,比如"取100块";有返回值,比如"取到的钱")
- 作用:你写的程序要访问硬件(比如打印文字、读文件),必须通过系统调用让OS帮忙
比如你用printf("hello")
,看似简单,其实是:你的代码→调用printf
(库函数)→printf
底层调用系统调用→OS让显示器显示"hello"。看这张图就懂了:
2. 库函数和系统调用的关系
库函数是"中介",把复杂的系统调用包装得简单。比如fopen
(打开文件)是库函数,底层其实调用了"打开文件"的系统调用------你不用管系统调用怎么写,直接用fopen
就行:

记住:只要库函数要访问硬件,底层一定藏着系统调用。
四、进程:正在"干活"的程序
你打开的微信、浏览器,甚至输的ls
命令,本质都是"进程"------简单说:进程 = 内核里的"身份信息"(task_struct) + 程序的代码和数据。
1. 进程的"身份证":task_struct(PCB)
OS要管多个进程,得给每个进程发"身份证"------所有系统都叫PCB(进程控制块),Linux里专门叫task_struct
,里面记着进程的所有信息:
比如:
- 标识符(PID):进程的唯一ID(像身份证号)
- 状态:运行中/暂停/退出
- 内存指针:程序代码在内存里的位置
OS管进程,其实就是管这些task_struct
------把它们用链表串起来,要启动/关闭进程,就是给链表增删节点:
2. 怎么查看进程?两种常用方法
方法1:用ps
命令
ps axj
:看所有进程ps axj | grep 进程名
:找特定进程(比如找myprocess
)
看这张图,20751
就是myprocess
的PID,想杀它就用ctrl+c
或kill -9 20751
:
方法2:看/proc
目录
Linux把每个进程做成一个目录,放在/proc
下------目录名就是进程的PID。比如/proc/21150
就是PID为21150的进程信息:
里面有两个关键文件:
exe
:指向磁盘里的可执行程序(比如你编译的myprocess
)cwd
:进程当前的工作目录(比如你在/home
下运行程序,cwd
就指向/home
)
比如你用fopen("test.txt", "r")
,程序会从cwd
目录找test.txt
------这就是相对路径能生效的原因:
想改工作目录?用chdir
函数(底层也是系统调用):
3. 进程的"父子关系":所有进程都有爹
Linux里没有"孤儿进程"------所有进程都是被其他进程创建的,创建者叫"父进程",被创建的叫"子进程"。
比如你打开命令行(bash
),输入./myprocess
,bash
就是父进程,myprocess
就是子进程:
甚至每个登录用户,OS都会分配一个bash
------你输的所有命令(ls
、cd
),父进程都是这个bash
:
4. 用代码创建子进程:fork函数
想自己写代码创建子进程?用fork()
就行------这是个系统调用,调用一次会返回两次(父进程和子进程各返回一次)。
先看代码和效果
代码长这样,编译运行后会同时打印父进程和子进程的信息:

运行后用ps
查看,能看到两个进程(PID分别是30382
和30383
):
关键问题:fork为啥这么"怪"?
(1)为啥返回两个值?
- 成功时:给子进程返回0 ,给父进程返回子进程的PID
- 失败时:给父进程返回-1
原因很简单:一个父进程能创建多个子进程,得用PID区分;而子进程只有一个父进程,不用记父PID------OS会帮它存好。
(2)为啥一个函数返回两次?
fork()
的核心是"创建子进程"------在执行return
之前,子进程已经被创建出来了,甚至已经开始跑了。所以执行return
时,父进程和子进程会各自执行一次,自然返回两次:

(3)为啥变量能又等于0又大于0?
看这段代码:父进程和子进程都改gval
,但最终结果不一样:
原因是进程有独立性 :默认共享代码和数据,但只要有一方改数据,OS会立刻拷贝一份数据给它------这叫"写实拷贝"。比如子进程改gval
,OS会给子进程拷贝一份gval
,父进程的gval
不变:
而且代码是"只读"的------父进程和子进程共享代码,谁也改不了,避免互相干扰:

最后总结
咱们从电脑的"底层规则"(冯诺依曼)讲到"管家"(OS),再到"干活的人"(进程),核心就三点:
- 程序要运行,必须先从磁盘加载到内存;
- 跟OS沟通只能用系统调用,库函数是"中介";
- 进程是运行的程序,OS用
task_struct
管它,创建子进程用fork
,且进程互相独立。
看懂这些,你就摸清了电脑运行的核心逻辑~