当前位置: 首页 > news >正文

从电脑底层到进程创建:一篇看懂冯诺依曼、OS和进程

前言:欢迎各位光临本博客,这里小编带你直接手撕Make/Makefile (自动化构建),文章并不复杂,愿诸君耐其心性,忘却杂尘,道有所长!!!!

解释_chmod_命令_(3).gif

**🔥个人主页:IF’Maxue-CSDN博客

🎬作者简介:C++研发方向学习者

📖个人专栏:
《C语言》
《C++深度学习》
《Linux》
《数据结构》
《数学建模》

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。不破不立,远方请直行!

文章目录

    • 一、冯诺依曼体系:电脑的“底层工作规则”
      • 1. 程序没运行时,藏在哪儿?
      • 2. “加载”就是挪食材的过程
      • 3. 存储分级:快的放近处,慢的放远处
      • 4. 两台电脑传文件,本质是啥?
    • 二、操作系统:电脑的“全能管家”
      • 1. 操作系统由两部分组成
      • 2. 管家怎么“管理”?核心是“先描述,再组织”
    • 三、系统调用:和“管家”沟通的唯一通道
      • 1. 系统调用像银行的“柜台”
      • 2. 库函数和系统调用的关系
    • 四、进程:正在“干活”的程序
      • 1. 进程的“身份证”:task_struct(PCB)
      • 2. 怎么查看进程?两种常用方法
        • 方法1:用`ps`命令
        • 方法2:看`/proc`目录
      • 3. 进程的“父子关系”:所有进程都有爹
      • 4. 用代码创建子进程:fork函数
        • 先看代码和效果
        • 关键问题:fork为啥这么“怪”?
          • (1)为啥返回两个值?
          • (2)为啥一个函数返回两次?
          • (3)为啥变量能又等于0又大于0?
    • 最后总结

一、冯诺依曼体系:电脑的“底层工作规则”

咱们先从最基础的说起——冯诺依曼体系,这其实就是电脑的“做事逻辑”,核心是所有硬件都围着“运算器”转,就像大家都听主厨的指挥一样。

image.png

1. 程序没运行时,藏在哪儿?

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

image.png

电脑有个死规矩:运算器只和内存打交道,键盘、磁盘这些外设也只跟内存交互。就像主厨(运算器)只用操作台上(内存)的食材,不会直接从冰箱(磁盘)拿——所以得先把“食材”(程序)从冰箱挪到操作台。

2. “加载”就是挪食材的过程

“加载”说直白点,就是把磁盘里的程序,拷贝到内存里。看这两张图,就是加载的完整流程:

image.png
image.png

加载完之后,运算器才能从内存里读指令、跑程序——这就是软件能运行的前提。

3. 存储分级:快的放近处,慢的放远处

电脑的存储不是一块铁板,而是分“快慢档”的,就像你把常用的东西放口袋,不常用的放柜子:

image.png

  • 最快:CPU缓存(口袋,随手拿)
  • 中等:内存(桌面,伸手够)
  • 最慢:磁盘(柜子,要起身开)

这里还有个“木桶原理”:程序跑多快,不看最快的硬件,只看最慢的那步。比如从磁盘拷到内存要1秒,哪怕运算器1毫秒能算完,整体还是得等1秒——所以效率由拷贝速度决定

image.png
image.png

4. 两台电脑传文件,本质是啥?

你给朋友发个照片,看似简单,其实是“两台冯诺依曼机器互相传食材”:本地磁盘→本地内存→网络→对方内存→对方磁盘。看这几张图,流程一目了然:

image.png
image.png
image.png

一句话总结:传文件就是“跨电脑的拷贝”。

二、操作系统:电脑的“全能管家”

有了硬件和底层规则,得有个“管家”来协调——这就是操作系统(OS),比如Windows、Linux、macOS。它的核心工作是管硬件、管软件,给你的程序提供舒服的运行环境

1. 操作系统由两部分组成

管家也分“核心”和“助手”:

image.png

  • 内核:管家的核心,管最底层的事(比如分配内存、控制CPU)
  • 其他程序:助手,比如图形界面(你电脑的桌面)、命令行工具

就连你的安卓手机,底层也是Linux内核——上面加了安卓的框架和APP,就像管家下面有专门管手机APP的助手:

image.png

2. 管家怎么“管理”?核心是“先描述,再组织”

不管管硬件还是程序,OS都遵循一个逻辑:先记清楚“对象是谁”,再把它们“分组管理”。比如学校管学生:

  1. 先描述:记每个学生的姓名、学号、班级(用表格或表单记录)
  2. 再组织:按班级分组,方便查改

OS管硬件也一样,看这几张图:

image.png
image.png
image.png

比如管内存,先记录“内存块大小、是否被占用”(描述),再用链表把这些记录串起来(组织)——后续分配/回收内存,就是改这个链表,跟校长改学生表格一样简单:

image.png
image.png

一句话:世界上所有管理,都是先记清楚属性,再分组整理——OS也不例外。

image.png
image.png

三、系统调用:和“管家”沟通的唯一通道

管家很谨慎,不相信陌生人——你不能直接闯进它的“后台”(内核),只能通过它开的“窗口”(系统调用)办事。

1. 系统调用像银行的“柜台”

比如你去银行取钱,不能直接进金库,得通过柜台——系统调用就是OS的“柜台”:

image.png

  • 本质:OS提供的C函数(有输入参数,比如“取100块”;有返回值,比如“取到的钱”)
  • 作用:你写的程序要访问硬件(比如打印文字、读文件),必须通过系统调用让OS帮忙

比如你用printf("hello"),看似简单,其实是:你的代码→调用printf(库函数)→printf底层调用系统调用→OS让显示器显示“hello”。看这张图就懂了:

image.png
image.png

2. 库函数和系统调用的关系

库函数是“中介”,把复杂的系统调用包装得简单。比如fopen(打开文件)是库函数,底层其实调用了“打开文件”的系统调用——你不用管系统调用怎么写,直接用fopen就行:

image.png

记住:只要库函数要访问硬件,底层一定藏着系统调用

四、进程:正在“干活”的程序

你打开的微信、浏览器,甚至输的ls命令,本质都是“进程”——简单说:进程 = 内核里的“身份信息”(task_struct) + 程序的代码和数据

1. 进程的“身份证”:task_struct(PCB)

OS要管多个进程,得给每个进程发“身份证”——所有系统都叫PCB(进程控制块),Linux里专门叫task_struct,里面记着进程的所有信息:

image.png
image.png

比如:

  • 标识符(PID):进程的唯一ID(像身份证号)
  • 状态:运行中/暂停/退出
  • 内存指针:程序代码在内存里的位置

OS管进程,其实就是管这些task_struct——把它们用链表串起来,要启动/关闭进程,就是给链表增删节点:

image.png
image.png
image.png

2. 怎么查看进程?两种常用方法

方法1:用ps命令
  • ps axj:看所有进程
  • ps axj | grep 进程名:找特定进程(比如找myprocess

看这张图,20751就是myprocess的PID,想杀它就用ctrl+ckill -9 20751

image.png
image.png

方法2:看/proc目录

Linux把每个进程做成一个目录,放在/proc下——目录名就是进程的PID。比如/proc/21150就是PID为21150的进程信息:

image.png
image.png

里面有两个关键文件:

  • exe:指向磁盘里的可执行程序(比如你编译的myprocess
  • cwd:进程当前的工作目录(比如你在/home下运行程序,cwd就指向/home

比如你用fopen("test.txt", "r"),程序会从cwd目录找test.txt——这就是相对路径能生效的原因:

image.png
image.png

想改工作目录?用chdir函数(底层也是系统调用):

image.png
image.png

3. 进程的“父子关系”:所有进程都有爹

Linux里没有“孤儿进程”——所有进程都是被其他进程创建的,创建者叫“父进程”,被创建的叫“子进程”。

比如你打开命令行(bash),输入./myprocessbash就是父进程,myprocess就是子进程:

image.png
image.png

甚至每个登录用户,OS都会分配一个bash——你输的所有命令(lscd),父进程都是这个bash

image.png
image.png

4. 用代码创建子进程:fork函数

想自己写代码创建子进程?用fork()就行——这是个系统调用,调用一次会返回两次(父进程和子进程各返回一次)。

先看代码和效果

代码长这样,编译运行后会同时打印父进程和子进程的信息:

image.png

运行后用ps查看,能看到两个进程(PID分别是3038230383):

image.png
image.png

关键问题:fork为啥这么“怪”?
(1)为啥返回两个值?
  • 成功时:给子进程返回0,给父进程返回子进程的PID
  • 失败时:给父进程返回-1

原因很简单:一个父进程能创建多个子进程,得用PID区分;而子进程只有一个父进程,不用记父PID——OS会帮它存好。

(2)为啥一个函数返回两次?

fork()的核心是“创建子进程”——在执行return之前,子进程已经被创建出来了,甚至已经开始跑了。所以执行return时,父进程和子进程会各自执行一次,自然返回两次:

image.png

(3)为啥变量能又等于0又大于0?

看这段代码:父进程和子进程都改gval,但最终结果不一样:

image.png
image.png

原因是进程有独立性:默认共享代码和数据,但只要有一方改数据,OS会立刻拷贝一份数据给它——这叫“写实拷贝”。比如子进程改gval,OS会给子进程拷贝一份gval,父进程的gval不变:

image.png
image.png

而且代码是“只读”的——父进程和子进程共享代码,谁也改不了,避免互相干扰:

image.png

最后总结

咱们从电脑的“底层规则”(冯诺依曼)讲到“管家”(OS),再到“干活的人”(进程),核心就三点:

  1. 程序要运行,必须先从磁盘加载到内存;
  2. 跟OS沟通只能用系统调用,库函数是“中介”;
  3. 进程是运行的程序,OS用task_struct管它,创建子进程用fork,且进程互相独立。

看懂这些,你就摸清了电脑运行的核心逻辑~

http://www.xdnf.cn/news/1427743.html

相关文章:

  • 【Qt开发】按钮类控件(二)-> QRadioButton
  • 【译】更好地控制您的 Copilot 代码建议
  • ResponseBodyEmitter介绍
  • Linux IPv4路由子系统深度解析
  • 什么是Token?——理解自然语言处理中的基本单位
  • 基于单片机颜色识别分拣系统设计
  • AI 生成视频入门:用 Pika Labs+Runway ML 制作短内容
  • 4.MySQL数据类型
  • day42-单片机
  • 【Linux基础知识系列:第一百一十六篇】使用mt进行磁带驱动管理
  • 第三家公司虽然用了powerbi,但更适合用excel
  • Flutter环境搭建全攻略之-windows环境搭建
  • 奔赴MOBILITY China 2026深圳新能源汽车技术展,共鉴行业高光时刻
  • 从零开始在Ubuntu上快速部署Docker和Dify:结合 Dify + 蓝耘 MaaS平台打造 AI 应用实战指南
  • Web基础学习笔记01
  • 计算机视觉与深度学习 | 视觉里程计技术全解析:定义、原理、与SLAM的关系及应用场景
  • Spring Boot 日志框架选择指南:Logback vs Log4j2
  • 破解能源密码——人造太阳:可控核聚变技术进展
  • 光储充一体化智慧能源平台助力某能投公司绿色能源转型
  • 【面试场景题】如何理解设计模式
  • 为什么研发文档的变更缺乏审批和追溯
  • 多通道电生理信号同步记录采集系统测试总结
  • 用好AI,从提示词工程到上下文工程
  • Linux系统强大的命令行工具之fuser
  • Vue + fetchEventSource 使用 AbortController 遇到的“只能中止一次”问题解析与解决方案
  • 详解 C++ 中的虚析构函数
  • 【系统架构设计(12)】系统运行与软件维护
  • 优选算法的映射之妙:哈希表专题
  • 【数据结构】八大排序之快速排序:分而治之的艺术
  • 从技术架构到经济价值:低代码在企业开发中的成本节约潜力