操作系统相关的一些问题总结

进程优先级调度

什么是进程优先级调度?

简单说,OS 会给每个进程分配一个 "优先级数值",调度器每次选 CPU 时,优先挑优先级最高的就绪进程运行。比如我们电脑里的杀毒软件后台扫描(低优先级),不会打断正在打字的编辑器(中优先级);而系统的内存管理进程(高优先级),哪怕编辑器在运行,也能优先占用 CPU 处理关键任务 ------ 这就是优先级调度的核心目的:资源向核心任务倾斜,平衡 "响应速度" 和 "资源利用率"

动态、静态优先级是什么?

  • 静态优先级:进程创建时就定好,后续基本不变(比如程序员通过nice命令设置,或系统默认分配)。比如 Linux 里nice值范围是 -20~19值越小,优先级越高-------20 是最高,19 是最低

  • 动态优先级:进程运行中,OS 根据行为动态调整。比如:

    • IO 密集型进程(比如浏览器、数据库,经常等磁盘 / 网络):OS 会提高优先级,因为它 "占着 CPU 的时间短",多给机会能让用户感觉更流畅;

    • CPU 密集型进程(比如视频渲染、数学计算,一直占 CPU):OS 会降低优先级,避免它独占 CPU,导致其他进程卡壳。

什么是两种调度策略?

  • 抢占式:高优先级进程就绪后,能直接 "打断" 正在运行的低优先级进程,抢占 CPU。比如你正在用播放器(中优先级),突然系统弹出杀毒提醒(高优先级)------ 播放器会暂时暂停,让提醒先显示,这就是抢占式的好处:关键任务响应快

  • 非抢占式:低优先级进程没跑完之前,高优先级进程只能等着,不能打断。现在很少用,缺点很明显:如果低优先级进程卡死,高优先级进程也没法运行。

什么时候换进程?

  • 进程主动放弃 CPU(比如调用sleep、等待 IO 完成);

  • 进程时间片用完(哪怕优先级高,也不能一直占着,比如 Linux 里高优先级进程时间片更长,但还是会轮换);

  • 新的高优先级进程就绪(比如刚创建的系统进程,或之前等待 IO 的高优先级进程完成等待);

  • 发生中断(比如键盘输入、网络数据到达)

常见的调度器

一、O(N)调度器

what?

这是最早期的调度器,它通过遍历整个就绪队列来寻找优先级最高的进程,时间复杂度是 O (N)

1、核心
  • 系统维护一个按优先级排序的链表数组,每个优先级对应一个链表。

  • 调度时,从最高优先级开始,逐个遍历链表,找到第一个可运行的进程。

  • 进程运行时,会消耗时间片,时间片用完后被移到低优先级队列或重新计算优先级

2、特点
  • 优点:实现简单,逻辑直观。

  • 缺点

    • 当就绪进程数量多时,遍历开销大,调度延迟高(比如几百个进程时,遍历要花不少时间)。

    • 高优先级进程可能长期霸占 CPU,导致低优先级进程 "饥饿"

二、O(1)调度器

what?

为解决 O (N) 的遍历开销而生,调度决策的时间复杂度是 O (1),不随就绪进程数量变化

1、核心
  • 双数组结构

    • active 数组:存放当前有时间片的进程,按优先级分组。

    • expired 数组:存放时间片用完的进程。

  • 位图索引:用一个位图(bitmask)记录哪些优先级有可运行进程,调度时通过位图快速定位最高优先级(位运算直接找第一个置1的位)。

  • 时间片分配 :高优先级进程时间片长,低优先级短,用完后移到 expired 数组,当 active 为空时,交换两个数组

2、特点
  • 优点:调度速度快,无论多少进程,找最高优先级进程都是 O (1) 操作。

  • 缺点

    • 对交互式进程优化不足(比如 IO 密集型进程可能因时间片用完被打入低优先级)。

    • 优先级数量有限(比如 256 个),灵活性不够

三、时钟中断

what?

调度器的 "触发器",通过硬件时钟定期触发调度,保证系统公平性和及时性

1、核心
  • 硬件时钟每 10ms ~ 100ms 产生一次中断(时钟节拍)。

  • 中断发生时,内核会:

    1. 更新系统时间。

    2. 减少当前进程的时间片,时间片为 0 时标记为 "需要重新调度"。

    3. 检查是否有更高优先级进程就绪,若有则触发抢占。

    4. 定期进行负载均衡(比如把进程从繁忙 CPU 移到空闲 CPU)

2、作用
  • 避免进程无限占用 CPU,保证时间片轮转。

  • 及时响应高优先级进程,实现抢占式调度。

  • 维护系统时间和进程运行统计信息

四、CFS(完全公平调度器)

what?

目前 Linux 默认调度器,基于 "完全公平" 思想,用虚拟运行时间(vruntime) 替代固定时间片,时间复杂度 O (logN)

1、核心
  • vruntime :进程的 "虚拟运行时间",计算公式为 实际运行时间 × (1024 / 进程权重)。优先级越高,权重越大,vruntime 增长越慢。

  • 红黑树:所有就绪进程按 vruntime 排序存入红黑树,调度时取树中 vruntime 最小的进程(最 "饥饿" 的进程)。

  • 时间片动态调整:没有固定时间片,进程运行一段时间后,若 vruntime 超过其他进程,会被抢占。

  • 交互式优化:IO 密集型进程(如键盘输入、鼠标操作)因经常睡眠,vruntime 增长慢,会被优先调度,保证响应速度

2、特点
  • 公平性好,每个进程获得的 CPU 时间与优先级成正比。
  • 对交互式进程友好,响应速度快。

  • 支持动态优先级调整,适应不同负载场景

五、总结

O (N)(简单但低效)→ O (1)(高效但不够灵活)→ CFS(公平且灵活) ,而时钟中断调度是所有调度器的基础触发机制

早期 Linux 用 O (N) 调度,遍历队列找进程,简单但进程多了就卡;后来升级到 O (1),用位图快速定位优先级,解决了遍历开销;现在主流是 CFS,用 vruntime 和红黑树实现完全公平,还优化了交互式体验;而这一切都离不开时钟中断,它定期触发调度,保证系统能及时切换进程,不卡顿

软硬链接

一、硬链接

what?

给文件的 inode 起一个新的文件名映射,多个硬链接指向同一个 inode,本质是 "同一个文件的不同名字",就像引用一样,是不独立的

实现

  • 在对应文件中将对应的inode编号所对应的文件名个数加一,ls命令可以展示count,同时加一个该inode与文件名的对应关系

  • 硬链接的创建:ln 原文件 硬链接文件 本质是 ------ 在目录的 data block 中,新增一条 "硬链接文件名→原文件 inode 编号" 的目录项

  • 关键细节(类比引用):

    • 原文件和硬链接文件的 inode 编号完全相同;

    • inode 中的 "链接计数(link count)" 会 + 1(比如原文件 link count=1,创建一个硬链接后变成 2);

    • 数据块和元数据(权限、大小、修改时间等)完全共享,修改任何一个,其他硬链接都会同步变化

二、软链接

what?

创建一个独立的新文件,该文件的 inode 数据块中存储的是 "原文件的路径",访问软链接时,系统会自动跳转去访问原文件,原文件与链接文件是相互独立的

实现

  • 软链接的创建:ln -s 原文件 软链接文件 本质是 ------ 创建一个全新的 inode(有独立的 inode 编号),该 inode 的 data block 中只存储 "原文件的绝对 / 相对路径"(比如/home/user/test.txt

  • 关键细节:

    • 软链接文件有自己独立的 inode,link count 始终为 1;

    • 软链接的文件类型标识为l(用ls -l查看时,首字符是l);

    • 访问软链接时,系统会先读取其 data block 中的路径,再根据路径去查找原文件的 inode,最终访问原文件的数据

三、对比

对比维度 硬链接(Hard Link) 软链接(Soft link)
inode 编号 与原文件完全相同(共享 inode) 有独立的 inode 编号(独立文件)
链接计数(link count) 原文件和硬链接的 link count 同步增减 软链接自身 link count 始终为 1
存储内容 无独立存储,共享原文件的数据块和数据 独立数据块,存储原文件的路径(绝对 / 相对)
原文件删除后 不影响,其他硬链接仍可正常访问(link count-1) 软链接失效(变成 "断链",ls 查看呈红色闪烁)
跨文件系统(如 ext4→NTFS) 不支持(inode 编号仅在当前文件系统内唯一) 支持(仅存储路径,与文件系统无关)
指向对象 仅能指向文件,不能指向目录 可指向文件或目录
路径类型 仅支持相对路径(基于当前目录) 支持绝对路径和相对路径
文件类型标识(ls -l) 与原文件一致(如-表示普通文件,d表示目录) 单独标识为l(link)
权限设置 与原文件共享权限(设置硬链接权限会同步影响原文件) 自身权限为rwxrwxrwx(但实际访问权限由原文件决定)

四、小问题

1. 为什么硬链接不能指向目录?

  • 核心原因:会导致目录树循环

  • 补充:目录的默认 link count 是 2(自身目录项 + 父目录的..指向),如果允许硬链接目录,会破坏目录树的层级结构和 link count 的计算逻辑。

2. 软链接的权限为什么是rwxrwxrwx?实际访问时以什么为准?

  • 表面权限是777,但这是 "假权限",实际访问软链接时,系统会穿透到原文件,以原文件的权限为准;

  • 比如软链接link.txt权限是rwxrwxrwx,但原文件test.txt权限是rw-r--r--,则普通用户只能读取link.txt,不能修改

  • link count 为 0 表示没有任何文件名指向该 inode,系统会回收该 inode 及其对应的数据块,文件彻底删除

4. 软链接变成 "断链" 的常见原因?

  • 原文件被删除或移动到其他路径

  • 软链接使用相对路径,且软链接文件被移动到其他目录(比如在/home创建ln -s test.txt link.txt,再把link.txt移到/root,访问时会找/root/test.txt,而原文件在/home

软硬链接的核心区别在于是否共享 inode:硬链接是文件的别名,共享 inode 和数据,删除原文件不影响,不能跨文件系统、不能指向目录;软链接是独立文件,存储原文件路径,原文件删除后失效,支持跨文件系统和目录

僵尸进程

what?

僵尸进程是已经终止运行,但父进程未处理其返回信息的进程

僵尸进程的危害

  • 进程进入僵尸状态之后,如果父进程一直不做处理,那么操作系统就要一直维护僵尸进程的退出信息,占用了CPU资源

  • 同时,内存中还要一直维护进程的PCB进程信息控制块,如果一直不做处理的话,PCB的内存将会泄漏

  • 进程pid是有限的,如果有大量的pid被僵尸进程占用,就不能创建新进程了

僵尸进程的处理

  1. 父进程调用wait()/waitpid(),回收子进程的退出信息

  2. 杀死父进程

为什么kill无法杀死僵尸进程?

  • 核心:僵尸进程已经终止运行,不再执行任何代码,kill信号的作用是 "通知进程执行特定操作"(如终止、暂停),但对已终止的进程无效;

  • 僵尸进程的残留是 "PCB 未回收",而非 "进程仍在运行",所以只能通过回收 PCB 的方式清除,不能用kill

相关推荐
牛奔1 小时前
php 8.2 配置安装php-zbarcode扩展
android·开发语言·php
人工智能训练1 小时前
Windows系统Docker中Xinference 集群无法启动的解决方法
linux·运维·服务器·windows·docker·容器·xinference
Andys1 小时前
C语言循环嵌套
c语言
Full Stack Developme1 小时前
Linux YUM、Docker 和源码编译
linux·运维·docker
曾几何时`1 小时前
基于VM虚拟机 ubuntu使用主机代理
linux·服务器·ubuntu
Fcy6481 小时前
C++ 模版(进阶)(含array解析)
开发语言·c++·stl·array·模版
OKkankan1 小时前
多态概念及使用
开发语言·数据结构·c++·算法
hudawei9961 小时前
kotlin协程编译成Android字节码后是什么样的
android·开发语言·kotlin