news 2026/7/11 12:24:12

线程如何从“跑代码”变成“让 OS 干活”?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
线程如何从“跑代码”变成“让 OS 干活”?

主要关注这四件事:

  • 为什么必须区分用户态 / 内核态?

  • 什么是系统调用?它解决了什么?

  • 系统调用与中断的关系是什么?

  • 一次系统调用在 OS 中发生了什么?(最小流程)

为什么必须有用户态 / 内核态?

从 前面几篇已知事实出发:

  • 程序共享 CPU

  • 程序共享机器

  • 程序不可信(可能崩溃 / 恶意 / Bug)

如果程序能直接:

  • 访问物理内存

  • 修改页表

  • 操作硬件

  • 控制中断

  • 修改调度器

那结果只有一个:

任何程序都可以破坏整个系统。

因此 OS 必须做一件事:

把“能干危险事的代码”和“普通程序代码”强制隔离。


两个模式由硬件强制区分

  • 用户态(User Mode)

    • 不能访问硬件

    • 不能操作页表

    • 不能关中断

    • 不能调度线程

  • 内核态(Kernel Mode)

    • 可以操作一切

    • 控制内存、CPU、设备、调度

这不是 OS 约定,是 CPU 硬件级强制。


那程序怎么“让 OS 干活”?——系统调用

问题来了:

用户态程序既然不能直接干危险事,
那它怎么读文件、发网络、创建线程?

答案只有一个:

系统调用(System Call)

系统调用的本质是:

用户态程序请求内核态代码代为执行受保护操作。

关键点:

  • 程序不能自己切到内核态

  • 只能通过CPU 提供的受控入口

  • 内核决定允不允许、怎么做、做多久


系统调用解决了什么?

  1. 安全:程序不能越权

  2. 隔离:只能操作自己的资源

  3. 统一管理:OS 统一调度 I/O、内存、线程

系统调用是用户态 → 内核态的唯一合法通道

系统调用 vs 中断

这是 这篇文章的 的关键区分点。


系统调用(System Call)

  • 谁触发?用户程序

  • 是否主动?

  • 目的?请求 OS 服务

  • 例子?read / write / fork / mmap


中断(Interrupt)

  • 谁触发?硬件

  • 是否主动?

  • 目的?通知 OS 事件发生

  • 例子?

    • 磁盘 I/O 完成

    • 网络包到达

    • 定时器中断(时间片)

核心一句话:

系统调用是“我想要”;中断是“事情发生了”。

一次系统调用的最小执行流程

不讲细节,只讲不可省略的骨架

read()为例:

[用户态]
程序调用 read(fd, buf, size)

CPU 执行 syscall / trap 指令

CPU 切换到内核态

进入内核的系统调用处理函数

内核检查参数 / 权限

如果数据未就绪 → 线程进入 Blocked

调度器切换到其他线程

(某个时刻)I/O 完成 → 硬件中断

内核处理中断,唤醒线程

线程回到 Ready → Running

系统调用返回

CPU 切回用户态

系统调用、阻塞、调度、中断
在这一条路径里全部串起来了。
这是五篇文章的完整闭环。

Day5 的三条不可混淆结论

① 用户态 / 内核态是硬件强制隔离,不是软件约定。

② 系统调用是用户态进入内核态的唯一合法方式。

③ 中断是硬件通知 OS 的机制,与系统调用完全不同。

接下来是对应的问题:

Q1:为什么必须区分用户态和内核态?(一句话)

Q2:系统调用的本质是什么?(一句话)

Q3:系统调用和中断的区别是什么?(一句话)

Q4:为什么用户态不能直接操作硬件或内存?(一句话)

Q5:一次 read() 可能为什么会阻塞?阻塞期间 CPU 在干什么?

回答完之后,OS主线就基本串联完成了。

标准答案:

Q1:为了防止用户程序直接操作硬件、内存和内核数据,从而破坏整个系统。

关键词必须包含:用户程序 / 硬件或内核 / 破坏系统

Q2:系统调用是用户态程序通过受控入口请求内核代为执行受保护操作。

Q3:系统调用是用户程序主动请求内核服务;中断是硬件被动通知内核事件发生。

Q4:因为用户态程序不可信,若能直接操作硬件或内存会破坏系统隔离与安全。

Q5:read 会因等待 I/O 数据而阻塞;阻塞期间线程进入 Blocked,CPU 被调度去执行其他线程。

原理解(用于自己复盘纠正):

Q1,为了系统安全(只有结果,没有因果,不够)
Q2,程序对系统内核申请权限并返回数据

“申请权限”这个说法不准确
系统调用不是动态申请权限,而是受控进入内核执行受保护操作

Q3,系统调用是用户态与内核态之间的机制,而中断是硬件层面和os的机制

不够精确,缺“主动 / 被动”这条关键分界线。

系统调用是用户程序主动请求内核服务;中断是硬件被动通知内核事件发生。

Q4,因为不安全

过于抽象,说完整一点= =

因为用户态程序不可信,若能直接操作硬件或内存会破坏系统隔离与安全。

Q5,read在等待os返回所需数据,阻塞期间cpu在请求系统内核的数据

直接把“线程在做什么”和“CPU在做什么”混到了一句话里。

即半对半错:

“这个 read 的请求已经交给内核 / 设备了,系统在处理 I/O”

这一点是对的,但——
处理 I/O 的不是 CPU 在“等着跑”

Q5 拆分成三层来理解:

1.线程在干什么?(Thread 视角)

线程调用 read()
→ 发现数据还没准备好
→ 被内核挂起
→ 状态变为 Blocked
→ 不再参与 CPU 调度

没后续了

2.那CPU在干嘛?(CPU / Scheduler 视角)

CPU 发现当前线程 Blocked
→ 立即进行一次调度
→ 切换上下文
→ 去执行其他 Ready 线程

CPU 从来不会“等 I/O 数据”。

CPU 只做两件事:

  • 执行指令

  • 切换执行对象

3.谁在跑I/O?(设备 / 中断视角)

磁盘 / 网卡 / DMA / 控制器
→ 在硬件层面异步处理 I/O
→ 完成后触发中断
→ 通知内核

I/O 处理是“设备在干活”,不是 CPU 在干活。

Q5修改后的答案:read 发起 I/O 请求后,线程被阻塞,CPU 去执行其他线程,I/O 由设备异步完成,完成后通过中断唤醒线程。

必须纠正:“阻塞”描述的是线程状态,不是 CPU 行为。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/11 9:31:18

零信任架构的测试验证:面向软件测试从业者的实践指南

在当今数字化时代,网络安全威胁日益复杂,传统的边界安全模型已无法满足企业对数据和系统的保护需求。零信任架构(Zero Trust Architecture, ZTA)作为一种新兴的安全范式,强调“从不信任,始终验证”的核心原…

作者头像 李华
网站建设 2026/7/10 15:59:10

如何用Qwen3-32B实现高级代码生成?实战案例分享

如何用Qwen3-32B实现高级代码生成?实战案例分享 在现代软件开发节奏日益加快的今天,工程师们面临一个共同挑战:如何在保证代码质量的前提下,大幅提升编码效率?重复性的模块编写、繁琐的测试用例构造、跨语言迁移时的理…

作者头像 李华
网站建设 2026/7/11 4:32:36

【C++】用哈希表封装unordered_map和unordered_set

1. 源码及框架分析SGI-STL30版本源代码中没有unordered_map和unordered_set,SGI-STL30版本是C11之前的STL版本,这两个容器是C11之后才更新的。但是SGI-STL30实现了哈希表,只容器的名字是hash_map和hash_set,他是作为⾮标准的容器出…

作者头像 李华
网站建设 2026/7/7 3:43:23

STL转STEP实战指南:从格式困境到工程级解决方案

你是不是也遇到过这样的烦恼?精心设计的3D打印模型,想导入SolidWorks、CATIA等专业软件进行二次开发,却发现STL格式根本不被识别?别着急,这正是STL转STEP转换能帮你解决的问题!在现代三维设计和制造领域&am…

作者头像 李华
网站建设 2026/7/10 19:27:21

隐私计算如何赋能大数据共享?关键技术全解析

隐私计算:破解大数据共享“数据孤岛”的钥匙——关键技术与实践全解析 引言:大数据共享的“痛”——想共享却不敢 你可能遇到过这样的场景: 银行想和电商联合做“信用评分模型”,但银行的用户金融数据和电商的用户行为数据都是“核…

作者头像 李华