操作系统进行线程切换时进行的动作
1. 保存当前线程的上下文
- 寄存器状态:保存 CPU 寄存器(如通用寄存器、程序计数器 PC、栈指针 SP 等)到当前线程的 线程控制块(TCB) 中。
- 内核栈信息:如果线程在内核态运行(例如因系统调用或中断进入内核),需保存内核栈指针。
- 浮点 / 向量寄存器:若线程使用了浮点运算或 SIMD 指令,需保存相关寄存器状态。
2. 更新线程状态与调度队列
- 将当前线程状态从 运行态(Running) 改为 就绪态(Ready)(例如时间片耗尽)或 阻塞态(Blocked)(例如等待 I/O)。
- 将其 TCB 移动到对应的调度队列(如就绪队列、阻塞队列)。
3. 调度器选择下一个线程
- 调度器根据算法(如时间片轮转、优先级)从 就绪队列 中选择一个线程,分配 CPU 使用权。
4. 恢复新线程的上下文
- 从新线程的 TCB 中加载其保存的寄存器状态(包括 PC、SP),恢复 CPU 执行环境。
- 切换内核栈(如果是内核级线程)。
5. 切换内存地址空间(可选)
- 同一进程内的线程切换:无需切换地址空间(共享同一进程的页表)。
- 跨进程的线程切换(如某些系统允许线程跨进程):需更新 内存管理单元(MMU),切换页表,刷新 TLB。
6. 更新系统状态
- 更新当前运行线程的指针(例如 Linux 的
current
宏)。 - 更新 CPU 的统计信息(如线程运行时间、调度次数)。
7. 执行新线程
- 通过恢复的程序计数器(PC)跳转到新线程的代码位置,继续执行。
触发线程切换的典型场景
- 主动让出 CPU:线程调用
yield()
或等待锁 / I/O。 - 时间片耗尽:时钟中断触发调度器介入。
- 高优先级线程就绪:抢占式调度强制切换。
什么是用户态和内核态
1. 用户态(User Mode)
- 权限:低权限模式,限制对硬件的直接访问。
- 执行主体:普通应用程序(如浏览器、文本编辑器)。
- 关键限制:
- 无法直接操作硬件(如磁盘、网络设备)。
- 内存访问受限:只能访问进程分配的虚拟内存,无法读写内核空间。
- 特权指令禁用:如修改页表、关闭中断等指令会被 CPU 拒绝执行。
- 目的:防止用户程序破坏系统或干扰其他进程。
2. 内核态(Kernel Mode)
- 权限:最高权限模式,可完全控制硬件和系统资源。
- 执行主体:操作系统内核(如处理中断、管理进程、驱动硬件)。
- 核心能力:
- 直接访问硬件:如读写磁盘、配置网络设备。
- 管理内存:修改页表、分配物理内存。
- 执行特权指令:如开关中断、修改 CPU 运行模式。
- 目的:保障操作系统对资源的绝对控制,确保系统安全。
切换时呈现8字型
进程间通信的方式有哪些
操作系统中的进程有几种状态
进程的调度算法
进程和线程的区别
进程是操作系统资源分配的基本单位,而线程是处理器任务调度和执行的基本单位.
什么是软中断什么是硬中断
硬中断是由外部设备产生的中断信号,具有强制中断、快速响应等特点;软中断是由软件指令触发的中断,具有软件触发、灵活性高、处理机制复杂等特点。
为什么要有虚拟内存
-
突破物理内存限制
当程序需要的内存超过实际物理内存时,系统将暂时不用的数据转移到硬盘的「交换空间」,腾出物理内存供急需的程序使用,避免内存耗尽导致崩溃。 -
支持多任务并行
允许同时运行多个大型程序(如视频剪辑 + 游戏),即使总内存需求远超物理内存,也能通过动态调度保持流畅。 -
内存隔离与安全
每个进程拥有独立的虚拟地址空间,程序 A 和程序 B 使用相同的虚拟地址时,实际映射到不同物理地址,防止数据篡改或越界访问。 -
简化开发与兼容性
程序员无需关注物理内存碎片化问题,虚拟内存提供连续的逻辑地址空间,降低开发复杂度;同时统一内存管理策略,提升跨硬件平台的兼容性。
分段与分页
分段(Segmentation)
定义:将程序的逻辑地址空间按功能划分为不同大小的段(如代码段、数据段、堆栈段等),每个段代表一个逻辑单元,可独立分配和管理。
特点:
- 逻辑划分:段与程序结构对应(如函数、模块),便于程序开发与保护。
- 动态大小:段长度由程序需求决定,灵活但易产生外部碎片。
- 二维地址:逻辑地址由段号 + 段内偏移组成(如
段A: 0x100
)。
示例:
程序被划分为代码段(存放指令)、数据段(存放变量)、堆栈段(函数调用栈),每个段独立加载到内存的不同位置。
分页(Paging)
定义:将逻辑地址空间和物理内存划分为固定大小的页(如 4KB),通过页表映射实现非连续内存分配。
特点:
- 物理划分:页是固定大小的物理单位(如 4KB),消除外部碎片。
- 一维地址:逻辑地址由页号 + 页内偏移组成(如
页3: 0xFF
)。 - 硬件支持:页表由硬件加速地址转换,但可能产生内部碎片。
示例:
程序被切分为多个 4KB 的页,分散存储在物理内存的页框中,操作系统通过页表记录页与页框的映射关系。
分段与分片
1. 分段(Segmentation)—— 传输层(TCP)
定义:TCP 协议将应用层数据分割为适合网络传输的较小单元(称为 TCP 段 / Segment),每个段添加 TCP 头部(含端口号、序列号、校验和等)。
目的:
- 适配网络传输的合理数据大小(避免数据过大导致底层分片)。
- 实现可靠传输:每个段独立编号,便于确认重传和按序重组。
过程示例:
假设应用层发送 3000 字节 的数据,TCP 根据 MSS(最大报文段长度,通常约 1460 字节) 将其分为 3 个段:
- 段 1:0~1459 字节(序号 = 0)
- 段 2:1460~2919 字节(序号 = 1460)
- 段 3:2920~3000 字节(序号 = 2920)
特点:
- 由传输层(TCP)完成,对应用透明。
- 接收端按序号重组数据,保证顺序。
2. 分片(Fragmentation)—— 网络层(IP)
定义:IP 协议将网络层数据包切割为更小的 IP 分片 / Fragment,以适应底层网络的 MTU(最大传输单元,如以太网 MTU=1500 字节)。
触发条件:当数据包大小超过某段链路的 MTU 时,路由器或主机进行分片。
目的:
- 解决不同网络链路 MTU 不一致的问题(如从以太网到 PPPoE 链路)。
- 分片后的数据包可独立传输,但重组由接收端完成。
分片示例:
若 IP 层收到一个 4000 字节 的数据包(IP 头部 20 字节 + 数据 3980 字节),而链路 MTU=1500 字节,则分片为:
- 分片 1:20 字节头 + 1480 字节数据(总 1500 字节,标志 MF=1,偏移 = 0)
- 分片 2:20 字节头 + 1480 字节数据(MF=1,偏移 = 185)
- 分片 3:20 字节头 + 1020 字节数据(MF=0,偏移 = 370)
特点:
- 由网络层(IP)处理,对传输层和应用层透明。
- 分片可能发生在传输路径中的任何路由器。
- 重组仅在最终接收端进行,中间设备不重组。
- 分片会降低网络效率(丢失任一分片需重传整个包)。
cpu的使用率和cpu的负载分别是什么,它们有什么关系
CPU 使用率
定义:CPU 在某一时间段内实际执行任务的时间占比(如 80% 表示 CPU 有 80% 时间在工作)。
核心意义:反映 CPU 的忙碌程度。
CPU 负载(Load Average)
定义:系统在单位时间内,正在运行和等待 CPU 资源的平均任务数(如负载为 4 表示平均有 4 个任务需处理)。
核心意义:反映系统的任务队列压力,与 CPU 核心数相关(如 4 核 CPU 负载临界值约 4)。
为什么网络IO会被阻塞(多角度)
什么是reactor
Reactor(反应器模式) 是一种事件驱动的编程模型,核心目的是高效处理高并发 I/O 请求。它通过非阻塞 I/O 多路复用(如 epoll
/select
)监听多个事件源(如网络连接),当事件触发时自动分发到对应的处理程序(回调函数),实现单线程 / 少量线程管理大量连接
IO模型有哪些
模型 | 数据准备阶段 | 数据复制阶段 | 同步 / 异步 | 适用场景 |
---|---|---|---|---|
阻塞 I/O | 阻塞 | 阻塞 | 同步 | 简单客户端 |
非阻塞 I/O | 非阻塞(轮询) | 阻塞 | 同步 | 低并发 + 实时性要求 |
I/O 多路复用 | 阻塞(多路等待) | 阻塞 | 同步 | 高并发服务(Nginx、Redis) |
信号驱动 I/O | 非阻塞(信号通知) | 阻塞 | 同步 | 特殊设备监控 |
异步 I/O | 非阻塞 | 非阻塞 | 异步 | 高性能服务器(需内核支持) |
select、poll、epoll 的区别
特性 | select | poll | epoll |
---|---|---|---|
底层数据结构 |
|
| 红黑树 + 就绪链表 |
最大描述符数量 | 默认 1024(可修改但效率下降) | 无限制(由系统内存限制) | 无限制(由系统内存限制) |
事件触发模式 | 水平触发(LT) | 水平触发(LT) | 支持水平触发(LT)和边缘触发(ET) |
内核 - 用户数据拷贝 | 每次调用需拷贝整个 | 每次调用需拷贝整个 | 通过 |
时间复杂度 | O (n),遍历所有 fd | O (n),遍历所有 fd | O (1),仅处理就绪事件 |
CFS(linux)
CFS 是 Linux 内核的默认进程调度器,自 2.6.23 版本(2007 年)引入,用于管理普通进程(非实时进程)的 CPU 时间分配。其核心目标是公平性,即让所有进程按优先级和权重公平共享 CPU 资源,避免单个进程长时间独占 CPU。
核心机制
-
虚拟运行时间(vruntime)
- 作用:跟踪每个进程的 “虚拟 CPU 使用时间”,公平性由
vruntime
决定。 - 计算方式:
- 实际运行时间 × 权重因子(权重由进程的
nice
值决定)。 nice
值越小(优先级越高),权重越大,vruntime
增长越慢,进程更易被调度。
- 实际运行时间 × 权重因子(权重由进程的
- 调度规则:选择红黑树中
vruntime
最小的进程运行。
- 作用:跟踪每个进程的 “虚拟 CPU 使用时间”,公平性由
-
红黑树(Red-Black Tree)
- 作用:高效管理所有可运行进程,按
vruntime
排序。 - 优势:插入、删除、查找的时间复杂度为 O(log N),确保高并发下调度效率。
- 作用:高效管理所有可运行进程,按
-
动态时间片
- 目标延迟(sched_latency_ns):默认 24ms,保证所有进程在此周期内至少运行一次。
- 最小粒度(sched_min_granularity_ns):默认 3ms,避免频繁上下文切换。
- 时间片计算:根据进程数和权重动态调整(如 4 个进程时,每个分到 6ms)。
-
优先级与权重
nice
值范围:-20(最高优先级)到 +19(最低优先级)。- 权重表:内核通过
prio_to_weight
数组将nice
值映射为权重值(如nice=0
对应权重 1024)。
阻塞模式和非阻塞模式
-
阻塞模式
- 适用简单场景(如单线程顺序处理),编程简单。
- 缺点:高并发下效率低(线程因等待 I/O 被挂起)。
-
非阻塞模式
- 必须配合 多路复用(
select
/epoll
) 或 轮询 使用,否则频繁检查会浪费 CPU。 - 边缘触发(ET)模式必须使用非阻塞,否则可能因未读完 / 写完数据导致永久阻塞。
- 优点:支持高并发,线程不会因 I/O 等待被阻塞。
- 必须配合 多路复用(
2. send
发送数据
场景 | 阻塞模式 | 非阻塞模式 |
---|---|---|
发送缓冲区有空间 | 将数据复制到内核缓冲区,返回实际写入的字节数(通常是全部数据)。 | 同左。 |
发送缓冲区无空间 | 线程挂起,直到缓冲区有足够空间。 | 立即返回 -1 ,设置 errno=EAGAIN/EWOULDBLOCK ;或返回已成功复制的部分字节数。 |
部分空间可用 | 等待直到缓冲区剩余空间足够容纳全部数据(可能被中断)。 | 立即复制尽可能多的数据,返回实际复制的字节数。 |