首页
关于
友链
推荐
肥啾解析
百度一下
肥啾GPT
Search
1
宝塔面板登录 phpMyAdmin 提示服务器和客户端上指示的HTTPS之间不匹配
321 阅读
2
Customer complaints evolve with in-car tech
222 阅读
3
JavaScript解析
182 阅读
4
所谓关系
149 阅读
5
人类果然都是好争斗的
126 阅读
默认分类
网游架设
手机游戏
python
PHP
Mysql
VBA
C++
JAVASCRIPT
javascript基础
Oracle
生产管理
计划控制
ERP系统开发
APS排产
MES研究
考勤系统
CPA
财管
实务
经济法
战略
审计
税法
藏书架
古典名著
世界名著
编程秘籍
攻防渗透
经管书籍
大佬传经
风雅读物
考试相关
心情格言
拾玉良言
外文报刊
外刊随选
Facebook
Twitter
China Daily
软考
登录
Search
标签搜索
期刊读物
古文
何瑜明
累计撰写
180
篇文章
累计收到
154
条评论
首页
栏目
默认分类
网游架设
手机游戏
python
PHP
Mysql
VBA
C++
JAVASCRIPT
javascript基础
Oracle
生产管理
计划控制
ERP系统开发
APS排产
MES研究
考勤系统
CPA
财管
实务
经济法
战略
审计
税法
藏书架
古典名著
世界名著
编程秘籍
攻防渗透
经管书籍
大佬传经
风雅读物
考试相关
心情格言
拾玉良言
外文报刊
外刊随选
Facebook
Twitter
China Daily
软考
页面
关于
友链
推荐
肥啾解析
百度一下
肥啾GPT
搜索到
180
篇与
的结果
2026-02-04
此内容被密码保护
加密文章,请前往内页查看详情
2026年02月04日
1 阅读
0 评论
0 点赞
2026-02-04
操作系统理论
一、进程的引入:为什么需要进程?问题背景:早期计算机一次只能运行一个程序。比如,你有一个计算程序和一个下载程序,你想边计算边下载,怎么办?解决方案:引入进程的概念,让多个程序可以“同时”运行。实际上,在单核CPU上,是通过快速切换来实现的,但给用户的感觉是同时运行。例子:你打开音乐播放器听歌,同时用浏览器上网。操作系统为每个程序创建了一个进程,并轮流执行它们(时间片轮转)。虽然CPU同一时刻只能执行一个进程,但由于切换很快,你感觉音乐和网页同时都在运行。二、进程是什么?具体例子:想象一个厨房(CPU)里有一个厨师(进程)。厨师要做一道菜(程序),他需要菜谱(代码)、食材(数据)、厨具(资源)。菜谱指明了步骤,但厨师在切菜的时候可能被叫去炒菜(切换),那么他必须记住切到哪了(保存现场),等他回来再接着切。进程的定义:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位。它包括代码、数据、程序计数器、寄存器、堆栈等。三、进程的状态与切换面对的问题:进程在运行中,有时需要等待外部事件(比如等待用户输入、等待磁盘读取数据),如果让CPU一直等待,就浪费了。如何提高CPU利用率?解决办法:让进程在等待时让出CPU,给其他就绪的进程使用。这就引入了进程状态。例子:假设有两个进程A和B。A需要从磁盘读取数据,于是操作系统将A的状态改为“阻塞”,并让B运行。当磁盘数据准备好后,再将A的状态改为“就绪”,等待CPU调度。典型的状态转换:就绪:进程已准备好,只等CPU。运行:进程正在CPU上执行。阻塞:进程等待某个事件(如I/O完成)。状态转换图:新建 → 就绪 ↔ 运行 → 终止 ↓ 阻塞四、进程的创建与终止创建:通过系统调用(如fork)创建新进程。例子:在Linux终端中,你输入ls命令,shell进程会调用fork创建一个子进程,然后子进程调用exec执行ls程序。终止:进程完成任务后,通过exit系统调用终止,释放资源(除了进程控制块PCB,最后会被父进程回收)。五、进程间通信(IPC)问题:进程之间是隔离的,不能直接访问对方的内存。但如果需要协作,比如一个进程生产数据,另一个进程消费数据,怎么办?解决办法:操作系统提供进程间通信的机制。具体例子:管道(pipe):就像一条水管,一端写,另一端读。例如,在shell中执行ls | grep .txt,shell创建两个进程,一个执行ls,一个执行grep,并用管道连接起来。ls的输出直接作为grep的输入。消息队列:进程A发送一个消息到队列,进程B从队列中读取。类似于发邮件。共享内存:两个进程可以访问同一块内存区域。这是最快的IPC方式,但需要同步机制(如信号量)来避免冲突。信号(signal):一个进程可以向另一个进程发送信号,比如按下Ctrl+C发送SIGINT信号终止进程。六、进程同步问题:当多个进程共享资源(比如共享内存、文件)时,可能会产生冲突。例子:有两个进程A和B,它们都要往同一个文件里写数据。如果A写了一半,B也开始写,那么文件内容就会混乱。解决办法:使用同步机制,确保同一时刻只有一个进程访问共享资源。具体方法:互斥锁(Mutex):进程在访问共享资源前加锁,访问完后解锁。其他进程必须等待锁释放。信号量(Semaphore):一个计数器,用来控制多个进程对共享资源的访问。比如,只有3个资源,信号量初始值为3,每有一个进程占用一个资源,信号量减1,当减到0时,其他进程必须等待。条件变量:用于等待某个条件成立。七、进程调度问题:有多个就绪进程,但CPU只有一个,先运行哪个?调度算法例子:先来先服务(FCFS):就像排队买票,先来的先服务。但如果有长进程先到,短进程就要等很久。短作业优先(SJF):优先运行估计运行时间最短的进程。这可以减少平均等待时间,但长进程可能一直得不到运行(饥饿)。时间片轮转(RR):每个进程分配一个时间片(比如100ms),时间片用完后,进程被剥夺CPU,放到就绪队列末尾。这样每个进程都能得到执行,但上下文切换开销较大。多级反馈队列:结合了多种算法。有多个队列,每个队列优先级不同,时间片大小也不同。新进程进入最高优先级队列,如果时间片用完还没结束,就降到下一级队列。这样短进程可以很快完成,长进程也会得到执行。八、上下文切换问题:当CPU从一个进程切换到另一个进程时,需要保存当前进程的状态,以便下次恢复。例子:进程A正在运行,时间片用完,操作系统要切换到进程B。那么,操作系统必须保存A的寄存器、程序计数器等状态到A的PCB中,然后从B的PCB中恢复B的状态,让B继续运行。开销:上下文切换需要时间,如果切换太频繁,CPU的有效工作时间就会减少。九、多线程与进程的关系问题:进程的创建、切换开销较大,而且进程间通信复杂。如果我们要在一个程序内同时做多件事,比如一个文档编辑器,一边接收用户输入,一边自动保存,一边进行拼写检查,怎么办?解决办法:引入线程。线程是进程内的执行单元,一个进程可以有多个线程,它们共享进程的资源(如内存、文件),但各自有独立的栈和寄存器。例子:一个Web服务器,每来一个客户端请求,就创建一个线程来处理。这样,多个请求可以同时被处理(在多核CPU上真正并行,单核上也是并发)。因为线程共享进程的内存,所以创建线程和线程间通信的开销比进程小。十、总结进程是操作系统资源分配的基本单位,它使得多个程序可以并发执行,提高了系统资源的利用率。但进程的创建、切换、通信都有开销,因此后来又引入了线程。理解进程的关键是理解它的状态转换、调度、同步和通信机制,这些都是为了解决多任务环境下的资源竞争和协作问题。{card-default label="线程概念" width=""}线程:进程内部的“多任务协作”一、为什么需要线程?—— 解决“进程内部并发”的问题问题场景:你使用Word编辑文档,希望同时进行拼写检查、自动保存、用户输入响应。如果用多进程实现,那么这些任务之间共享数据(文档内容)会非常麻烦(需要进程通信),而且创建进程的开销较大。解决方案:在一个进程内部创建多个线程,每个线程执行不同的任务,共享同一份数据。具体实现:线程是进程内的执行单元,一个进程可以有多个线程同一进程的线程共享内存空间(代码段、数据段、打开的文件等)每个线程有独立的栈和程序计数器例子:Word进程中的多线程Word进程: 线程1:处理用户输入(键盘、鼠标) 线程2:定时自动保存 线程3:拼写和语法检查 线程4:打印文档二、线程是什么?—— 进程的“分身”比喻:餐厅厨房里的多个厨师整个厨房 = 进程(拥有食材、厨具等资源)每个厨师 = 线程(共享厨房资源,各自做一道菜)厨师间的协作 = 线程通信(直接说话,因为共享空间)具体例子:Web服务器处理多个客户端请求单进程多线程模型: 主线程:监听端口,接受连接 工作线程1:处理客户端A的请求 工作线程2:处理客户端B的请求 工作线程3:处理客户端C的请求 所有线程共享服务器资源(如缓存、数据库连接池) 线程共享的“公共空间” vs 私有的“个人空间”进程内的线程共享资源指的是:进程的地址空间中的大部分区域,包括代码段、数据段、堆、以及打开的文件描述符等。而每个线程拥有自己独立的栈空间(用于保存局部变量和函数调用信息)以及线程私有的上下文(如寄存器状态、程序计数器等)。具体来说:代码段:所有线程执行相同的代码,它们共享进程的代码段(即程序的可执行代码)。数据段:包括全局变量和静态变量,所有线程都可以访问和修改这些变量,因此需要同步机制来避免竞态条件。堆:动态分配的内存(如malloc/new分配的内存)是共享的,所有线程都可以访问堆中的同一块内存。文件描述符:进程打开的文件、网络套接字等,所有线程共享这些文件描述符,因此一个线程打开的文件,另一个线程也可以读写。信号处理程序:进程设置的信号处理函数是共享的,但每个线程可以有自己独立的信号屏蔽字。当前工作目录:进程的当前工作目录是共享的,一个线程改变工作目录会影响其他线程。用户ID和组ID:进程的用户ID和组ID是共享的。每个线程私有的资源包括:线程ID:每个线程有唯一的ID。寄存器状态:包括程序计数器、栈指针等,每个线程有自己的寄存器状态。栈:每个线程有自己独立的栈,用于存储局部变量、函数调用链等。线程之间不能直接访问其他线程的栈。信号屏蔽字:每个线程可以独立设置阻塞或解除阻塞某些信号。线程私有数据:有些系统支持线程私有数据(Thread Local Storage, TLS),即每个线程可以拥有某些数据的独立副本。理解线程共享哪些资源非常重要,因为这直接影响到多线程程序的设计和同步机制的使用。例如,共享的数据需要加锁保护,而线程私有的数据则不需要。三、线程 vs 进程 —— 详细对比四、线程同步——解决“共享数据混乱”问题问题场景:两个线程同时操作同一个银行账户,一个取钱,一个存钱,如果没有同步,账户余额可能会出错。互斥锁(Mutex)—— 卫生间一次只能一个人用// 银行账户例子 int balance = 1000; // 共享变量 pthread_mutex_t lock; // 线程A:取钱100 pthread_mutex_lock(&lock); int temp = balance; temp -= 100; balance = temp; pthread_mutex_unlock(&lock); // 线程B:存钱200 pthread_mutex_lock(&lock); int temp = balance; temp += 200; balance = temp; pthread_mutex_unlock(&lock);条件变量(Condition Variable)—— 排队等空位// 生产者-消费者问题(线程版) queue buffer; // 共享缓冲区 pthread_mutex_t mutex; pthread_cond_t cond_full; // 缓冲区满的条件变量 pthread_cond_t cond_empty; // 缓冲区空的条件变量 // 生产者线程 pthread_mutex_lock(&mutex); while (buffer.is_full()) { pthread_cond_wait(&cond_full, &mutex); // 等待缓冲区不满 } buffer.push(item); pthread_cond_signal(&cond_empty); // 通知消费者缓冲区不空了 pthread_mutex_unlock(&mutex); // 消费者线程 pthread_mutex_lock(&mutex); while (buffer.is_empty()) { pthread_cond_wait(&cond_empty, &mutex); // 等待缓冲区不空 } item = buffer.pop(); pthread_cond_signal(&cond_full); // 通知生产者缓冲区不满了 pthread_mutex_unlock(&mutex);读写锁(Read-Write Lock)—— 图书馆规则场景:多个线程同时读一个配置,偶尔有线程写配置 规则: 1. 可以多个线程同时读 2. 写的时候不能有任何其他读或写 实现: 读写锁有三种状态:读模式加锁、写模式加锁、不加锁 写模式加锁时,其他线程的读或写都会被阻塞 读模式加锁时,其他线程的写会被阻塞,但读可以继续五、线程池——避免“频繁创建销毁线程”的开销问题场景:Web服务器为每个请求创建一个新线程,请求处理完后销毁。当请求很多时,创建和销毁线程的开销很大。解决方案:预先创建一组线程,重复使用。线程池组成:1. 任务队列:存放待处理的任务 2. 工作线程:从任务队列取任务执行 3. 管理器:创建、销毁线程,调整线程数量例子:Java中的线程池ExecutorService pool = Executors.newFixedThreadPool(10); // 创建10个线程的池 // 提交100个任务 for (int i = 0; i < 100; i++) { pool.submit(new Task(i)); } pool.shutdown(); // 关闭线程池优势:降低资源消耗:重复利用已创建的线程提高响应速度:任务到达时,线程已存在,无需等待创建提高可管理性:可以统一管理线程调试多线程问题常见问题与排查工具问题1:竞态条件症状:结果不确定,每次运行可能不同 工具:ThreadSanitizer (TSan)、Helgrind问题2:死锁症状:程序卡住,不响应 工具:jstack (Java)、pstack、gdb 例子:jstack <pid> | grep -A 10 deadlock问题3:活锁症状:线程忙碌但无进展 例子:两个线程互相"礼让",都不断重试失败问题4:资源泄漏症状:内存或线程数持续增长 工具:jvisualvm、top -H、pmap总结:线程使用指南黄金法则:能不共享就不共享:减少共享数据,避免同步问题能无锁就无锁:使用原子变量、不可变对象必须同步时,粒度尽量小:减少锁竞争优先使用高级工具:线程池、并发集合、同步工具类线程是强大的并发工具,但"能力越大,责任越大"。理解其原理,遵循最佳实践,才能写出正确高效的多线程程序。现代软件中的线程使用案例1:Android应用的主线程与工作线程// Android中,UI操作必须在主线程(UI线程) class MainActivity : AppCompatActivity() { fun loadUserData(userId: String) { // 在后台线程执行耗时操作 thread { val userData = apiService.getUserData(userId) // 网络请求(可能耗时) // 回到主线程更新UI runOnUiThread { textView.text = userData.name // UI操作必须在主线程 progressBar.visibility = View.GONE } } } }规则:主线程只处理UI更新和用户交互,耗时操作(网络、数据库、计算)必须放在工作线程。案例2:Redis的单线程模型(为什么快?)Redis核心是单线程的,但性能极高,原因: 1. 纯内存操作:无磁盘I/O阻塞 2. 非阻塞I/O:使用epoll多路复用 3. 避免锁竞争:单线程不需要同步 4. 数据结构优化:高效的数据结构 适用场景:高并发、数据量小、读写频繁 不适用场景:复杂计算、大数据处理案例3:Nginx的多进程+多线程混合模型Nginx架构: ┌─ Master进程(管理)─────────────────────┐ │ ├─ Worker进程1(独立) │ │ │ ├─ 线程1:处理连接A │ │ │ ├─ 线程2:处理连接B │ │ │ └─ 线程池:处理磁盘I/O │ │ ├─ Worker进程2(独立) │ │ └─ Worker进程N(独立) │ 设计优点: 1. 进程隔离:一个Worker崩溃不影响其他 2. 线程共享:同一Worker内线程共享缓存 3. 充分利用多核:每个Worker绑定一个CPU核心{/card-default}虚拟存储管理系统的基础是程序的局部性理论,这个理论的基本含义是指程序执行时往往不会均匀地访问主存储器单元。根据这个理论,Denning 提出了工作集理论。工作集是进程运行时被频繁访问的页面集合。在进程运行时,如果它的工作集页面都在主存储器(内存)内,能够使该进程有效地运行,否则会出现频繁的页面调入/调出现象。{card-default label="局部性原理" width=""}局部性原理是虚拟存储技术的理论基础,包括两个方面:时间局部性:如果程序中的某条指令或数据被访问,那么不久之后它很可能再次被访问。典型例子包括循环、重复调用的函数等。空间局部性:如果程序访问了某个存储单元,那么其附近的存储单元也可能很快被访问。典型例子包括顺序执行的指令、数组的连续访问等。基于局部性原理,程序运行时只需将当前使用的部分页面装入内存,而非全部程序,从而实现虚拟存储器的高效管理。{/card-default}{card-default label="工作集理论" width=""}{/card-default}{card-default label="抖动(Thrashing)" width=""}当系统内存资源不足时,进程的工作集无法完全驻留内存,导致频繁的页面置换(调入/调出)。此时,CPU 大量时间用于处理缺页中断,实际工作效率下降,这种现象称为“抖动”。防止抖动的常用方法是采用工作集模型,确保每个活跃进程的工作集常驻内存,或采用页面置换算法(如工作集时钟算法)来动态调整内存分配。{/card-default}{card-default label="虚拟存储管理" width=""}虚拟存储技术允许程序部分装入内存即可运行,通过缺页中断机制和页面置换算法,实现内存的自动管理。其核心思想正是基于局部性原理:程序在一段时间内访问的页面相对集中,因此只需将这部分页面保留在内存中即可高效运行。工作集理论为虚拟存储器的内存分配和置换策略提供了重要指导。{/card-default}进程通信PV操作与信号量核心知识点总结初值=0 意味着初始状态没有任何可用资源,事件未发生,必须等待通知P操作 就像"瞅一眼桌子",发现没饭就睡觉(进程阻塞)V操作 就像"外卖员按门铃",把你叫醒继续执行(进程唤醒)原子性保证:// 假设S=1,两辆车同时P操作 车A: 读取S=1 → S--=0 → 进入停车场 车B: 读取S=1 → S--=0 → 也进入停车场 ❌ // 结果:一个车位停两辆车!碰撞!正确顺序:先P资源信号量,再P互斥信号量原理:如果先拿锁,当资源耗尽时,其他进程无法进入临界区释放资源,形成死锁初值=1:商场厕所(互斥访问)场景:只有一间厕所,拉屎要排队数据库行锁:1个线程修改,其他线程阻塞打印机互斥:1个人打印,其他人排队技术映射:保护临界区,一次只允许一个进程访问初值=N:停车场(资源池)场景:10个车位,先到先得图书馆座位:初值=500个座位数据库连接池:初值=5个连接线程池任务队列:初值=100个任务容量资源申请顺序不一致Process1 { P(A); P(B); ... V(B); V(A); } // 先A后B Process2 { P(B); P(A); ... V(A); V(B); } // ❌ 先B后A // 结果:Process1占A等B,Process2占B等A → **死锁!**正确:全局统一起始顺序Process1 { P(A); P(B); ... } Process2 { P(A); P(B); ... } // ✅ 顺序一致信号量负值理解错误题目:3个进程共享1台打印机,信号量初值=1,当前值=-2,问什么情况?❌ 错误答案:有2台打印机空闲(完全错误!)✅ 正确答案:2个进程在等待打印机(|-2|=2)编写PV操作(黄金顺序)Process { 准备工作; P(资源信号量); // 1️⃣ 先检查资源是否可用 P(互斥信号量); // 2️⃣ 再进入临界区(上锁) 操作共享资源; // 3️⃣ 临界区代码 V(互斥信号量); // 4️⃣ 先出临界区(解锁) V(通知信号量); // 5️⃣ 再通知其他进程 后续操作; }📌 初值选择:互斥用1,同步用0,资源就是N📌 PV本质:P是申请,不够就等;V是释放,唤醒他人📌 操作顺序:先资源后锁,先解锁后通知📌 信号量值:正数可用,零刚好用,负数等几📌 死锁避免:统一申请顺序,限制最大并发进程调度知识点进程调度本质核心问题:CPU只有一个,成百上千个进程要运行,按什么顺序执行?生活类比:餐厅只有一个厨师,怎么安排炒菜顺序才能让顾客最满意?{card-default label="六大调度算法" width=""}1.先来先服务(FCFS)原理:排队买奶茶,先到先得典型问题:护航效应(长作业阻塞短作业)2.短作业优先(SJF)原理:执行时间短的优先,分抢占/非抢占问题:长作业可能饿死生活场景:快餐店小份餐优先出餐,大胃王套餐最后做3.优先级调度原理:按优先级执行,分静态/动态优先级生活场景:医院急诊分级(濒危>危重>急症>非急症)数字越小优先级越高进程 | 到达 | 执行 | 优先级 P1 | 0ms | 8ms | 3 P2 | 1ms | 4ms | 1 ← 最高 P3 | 2ms | 9ms | 4 抢占式执行 0----1----5----14 |P1 |P2 |P1 |P34.时间片轮转(RR)原理:每个人轮流吃一口,看起来都很忙生活场景:自助餐每人限时5分钟,轮流用餐时间片=5ms执行示例:进程 | 到达 | 执行 P1 | 0ms | 13ms P2 | 1ms | 4ms P3 | 2ms | 6ms 0---5---9---15---18 |P1 |P2 |P3 |P15.多级队列调度原理:按性质分多个队列,不同队列不同策略生活场景:火车站分窗口:军人/急客窗口(优先级+RR)普通窗口(FCFS)团购窗口(批处理)前台队列(交互式):RR调度,时间片=8ms 后台队列(批处理):FCFS,时间片=32ms 系统队列(内核):优先级最高 队列规则:进程固定属于某队列队列间按优先级调度队列内用各自算法6.多级反馈队列(MFQ)原理:RR + 优先级 + 队列升级(Linux实际使用)生活场景:餐厅会员体系:新客→普通座(Q0)超时用餐→升包厢(Q1)长期用餐→升VIP(Q2)Q0(优先级最高):RR时间片=8msQ1:RR时间片=16msQ2(最低):FCFS时间片=32ms核心规则:新进程进入Q0用完时间片未结束 → 降级到下一队列等待过久未执行 → 提升到上级队列高优先级队列非空时,不执行低优先级{/card-default}{card-default label="核心计算模板" width=""}P1: 到达=0, 执行=7 P2: 到达=2, 执行=4 P3: 到达=4, 执行=1 0-3: P1 → 3-6: P2 → 6-7: P3 → 7-10: P2 → 10-14: P1 进程 | 到达 | 服务 | 完成 | 周转 | 带权 | 等待 P1 | 0 | 7 | 14 | 14 | 2.0 | 0+(10-3)=7 P2 | 2 | 4 | 10 | 8 | 2.0 | (3-2)+(7-6)=2 P3 | 4 | 1 | 7 | 3 | 3.0 | 6-4=2 计算平均值 平均等待 = (7+2+2)/3 = 3.67ms 平均周转 = (14+8+3)/3 = 8.33ms 平均带权 = (2+2+3)/3 = 2.33陷阱1:抢占式vs非抢占式混淆错误:题目说"抢占式SJF",却按非抢占计算正确:SRTF要在每个新进程到达时重新选择最短剩余时间P1(执行10ms)运行中,P2(执行1ms)到达 → 立即抢占P1执行P2 ✅陷阱2:时间片轮转切换开销忽略时间片=5ms,切换开销=1ms P1(0-4)运行 → P2(5-9)运行 → 实际耗时不是5ms而是6ms!陷阱3:带权周转时间算错执行时间=3ms,周转=24ms 带权 = 24/3 = 8 ✅ 不是 3/24 = 0.125 ❌陷阱4:响应时间理解错误错误:认为响应时间=结束时间正确:响应时间=首次运行时间-到达时间(第一次被调度)陷阱5:多级队列饥饿问题低优先级队列进程永远不执行 → 解决方案:优先级老化(等待越久优先级越高)陷阱6:护航效应识别题目:长作业+多个短作业用FCFS后果:短作业等待时间巨长 → 解决方案:用SJF或RR{/card-default}现实操作系统应用Linux CFS调度器核心理念:完全公平调度(Completely Fair Scheduler)关键技术:红黑树管理进程,按虚拟运行时间vruntime排序计算公式:vruntime = 实际时间 × (NICE_0_LOAD / 权重)调度周期:所有进程至少运行一次的时间生活类比:班级轮流发言,说话时间短的人优先Windows调度器32级优先级:0-31,0为最低动态调整:前台窗口线程+2,I/O操作后+1实时优先级:16-31级(需管理员权限实时系统调度硬实时 必须准时完成 最早截止时间优先(EDF)软实时 偶尔超时允许 速率单调调度(RMS)案例:导弹控制→EDF算法;视频播放器→RMS算法进程调度就是CPU的"交通警察":FCFS是排队,SJF是绿色通道,RR是轮流执政,多级反馈是智能交通系统,最终目标——让所有"车辆"都满意!{card-default label="进程资源图" width=""}分配边:进程与具体某个已持有实例的关系。(历史:已满足的请求)申请边:进程与整个资源类的关系。(当前:一个新的、未满足的请求)在进程资源图中,箭头是描述进程和资源之间关系的关键元素,它清晰地表达了资源的申请和分配状态。简单来说,箭头从谁指向谁,就表示“谁需要谁”或“谁等待谁”。申请边(Request Edge)方向:从 进程 指向 资源类(方框)。涵义:表示该进程正在申请(等待)该资源类中的一个实例,但尚未得到。状态:进程因此被阻塞,处于等待状态。口语化理解:“进程想要一个这种资源,但还没拿到。”分配边(Assignment Edge) / 持有边(Allocation Edge)方向:从 资源类中的某个具体实例(方框中的圆点)指向 进程。涵义:表示该资源类中的一个具体实例已经分配给了这个进程,由该进程持有。状态:进程正占用着此资源。口语化理解:“这个资源实例已经在进程手里了。如果资源有空闲,请求会被瞬间满足,申请边在快照中就不会出现(它会被立即转换为一条分配边)。因此,在静态资源图分析中,默认图中出现的每一条申请边都对应一个被阻塞的进程。假设资源有三个能分配的资源,但是已经有三个分配箭头了,这时还有一个申请边,那就是阻塞关于b图:R2的3个资源已经占用了2个,当进程P1和P3请求占用R2的时候,无论分配给哪一方都可以使两个进程都满足所需的资源,从而可以化简,P2也可得所需的R1资源。因此P1和P3是非阻塞节点。疑问:“申请边存在不是意味着阻塞吗?”是的,在静态快照中,画出的申请边意味着该进程在快照时刻因该请求而处于阻塞状态。但是,在动态化简分析中,我们关心的是这种阻塞是否是“永久性的”。如果系统当前有足够的空闲资源能立即(或在其他进程释放资源后)满足该请求,那么这个阻塞就是暂时的、可解除的。这样的进程在化简中就被归为“非阻塞节点”。“非阻塞节点”的真实含义:更准确的说法是“可立即满足或可被化简的节点”。它不是指进程在快照时刻未阻塞,而是指从当前系统状态出发,该进程的请求能够在不引起死锁的情况下被满足。{/card-default}动态分区内存管理中的空闲分区合并(或合并自由块)在动态分区分配方式中,当进程运行结束释放内存时,系统会将其占用的分区回收,并检查该分区是否与相邻的空闲分区相邻(地址连续)。如果回收区与上方和下方的空闲区都相邻,则系统会将这三个分区合并为一个更大的空闲分区,从而导致空闲区总数减少1。此过程旨在减少外部碎片,提高内存利用率。要保证系统中 6 个并发进程(每个进程都需要 2 个互斥资源 R)不发生死锁,资源 R 的最少数目为 7。推导过程:在最坏情况下,每个进程都已获得 1 个资源,同时还需要 1 个资源才能继续执行。此时如果系统中只剩 1 个可用资源,则可分配给任意一个进程,使其满足全部资源需求并运行完毕,之后释放的资源又能供其他进程使用,从而避免死锁。因此,最少资源数 = 进程数 × (每个进程所需资源数 - 1) + 1 = 6 × (2 - 1) + 1 = 7。{card-default label="其它知识点" width=""}电脑开机后,操作系统(如Windows、macOS、Linux)的核心部分确实会被从硬盘(或SSD)加载到内存(RAM)中运行。这是计算机启动和运行的标准流程。WINDOWS系统中设置默认路由的作用是当没有其它路由可选时最后选择的路由。操作系统的定义与功能:操作系统是管理计算机硬件与软件资源的系统软件,为用户和应用程序(如DBMS)提供一个方便、有效且一致的接口。其核心功能包括进程管理、存储管理、设备管理、文件管理和作业管理。{/card-default}
2026年02月04日
23 阅读
0 评论
0 点赞
2026-01-29
此内容被密码保护
加密文章,请前往内页查看详情
2026年01月29日
1 阅读
0 评论
0 点赞
2026-01-28
主流数据库应用
分布式数据库分布式数据库(Distributed Database)是指数据物理上分布在网络的不同节点(场地),但逻辑上是一个统一数据库的系统。核心目标透明性:对用户隐藏数据分布的细节,像使用单一数据库一样。可用性与可靠性:通过多副本提高容错能力。可扩展性:通过增加节点来扩展存储与处理能力。高性能:数据就近访问,并行处理。透明性分类位置透明性:用户无需知道数据存储在哪复制透明性:用户无需知道数据有几个副本分片透明性:用户感觉不到数据被分区事务透明性:分布式事务的执行如同本地事务为什么叫“透明性”?分布式数据库设计的最高目标,是让用户在使用时,完全感觉不到“分布”这件事。它追求的不是简单地“把复杂的网络、多节点、数据分片给藏起来”,而是要让这些复杂性在用户的体验层面根本不存在。分布式数据库的核心准则包括:本地自治、分布透明性(含分片透明、位置透明、复制透明等)、数据独立性、连续操作等。而“依赖中心结点”违背了分布式系统去中心化、高可用的基本原则,因此它不是应遵循的准则,而是需要避免的设计缺陷。{card-default label="数据分布策略" width=""}{/card-default}ACID 挑战在分布式环境下,原子性(A)和一致性(C)的实现需要额外协议。{card-default label="分布式事务协议" width=""}两阶段提交(2PC):【表决和执行阶段】协调者 + 参与者阶段一:准备(投票)阶段二:提交/回滚缺点:阻塞、协调者单点故障三阶段提交(3PC):引入超时机制减少阻塞,但仍可能数据不一致。Paxos/Raft:用于保证多副本一致性的共识算法,常用于副本同步。{/card-default}一致性模型强一致性:任何时刻所有节点看到的数据一致(如分布式事务)最终一致性:在一段时间无更新后,所有副本最终一致(如DNS、Cassandra){card-default label="数据分区与路由" width=""}常见分区方案范围分区:按主键范围划分(容易热点)哈希分区:对分区键哈希取模(分布均匀,但范围查询难)一致性哈希:增加/删除节点时数据迁移少,常用于分布式缓存(如Redis Cluster)全局索引 vs 本地索引本地索引:仅覆盖本节点数据,跨节点查询需合并全局索引:跨所有节点,维护成本高{/card-default}主流分布式数据库分类与技术核心挑战与解决方案{card-default label="典型架构模式" width=""}共享存储式:计算节点共享同一存储(如AWS Aurora),存储层自己处理复制与一致性。分片共享无共享(Shared-Nothing):每个节点独立存储与计算,通过网络协作(如TiDB、Cassandra),扩展性最好。中间件代理式:通过中间件(如MyCAT、ShardingSphere)路由SQL,底层是多个独立数据库。{/card-default}{card-default label="分布式数据库系统(DDBS)按局部数据模型异同的分类" width=""}分布式数据库系统根据各参与场地(节点)使用的局部数据模型和数据库管理系统(DBMS)是否相同,分为两类:同构型 DDBS定义:所有场地都采用相同类型的数据模型(如都是关系型)和相同的数据库管理系统(如都是 Oracle 或都是 MySQL)。特点:设计和管理相对简单,数据集成和查询处理容易。例子:一个全球性公司,所有分部的数据库都统一使用 MySQL。异构型 DDBS定义:各场地采用不同类型的数据模型(如有的用关系型,有的用层次型或网状型)和/或不同的数据库管理系统。特点:更符合现实(因历史遗留系统往往不同),但实现复杂,需要解决数据模型转换、模式集成、查询翻译等问题。例子:题目中描述的“层次型或关系型”混合的场景,就是典型的异构型。{/card-default}{card-default label="分布式数据库(DDBS)体系结构中的模式层次" width=""}在分布式数据库系统中,通常采用三级模式结构,并且这三级模式可以分为全局和局部两个层面。具体来说:全局模式:描述分布式数据库中所有数据的全局逻辑结构,与集中式数据库的概念模式类似。分片模式:描述全局数据如何划分成逻辑片段(分片)。它定义了全局关系与片段之间的映射。分配模式:描述片段如何物理地分配到各个场地(节点)。它定义了片段与场地之间的映射。分片模式和分配模式都是针对全局数据的逻辑划分和物理分布进行定义的,因此它们属于全局层次,而不是局部层次。局部层次是指每个场地上局部数据库的模式。所以,分片模式和分配模式均是全局的。在分布式数据库系统(DDBS)中,数据分片(Data Fragmentation)是指将全局数据库(或表)逻辑划分为多个片段(如水平分片、垂直分片),以便分布存储到不同站点。这一概念关注的是数据库逻辑层面的划分,而非物理存储介质。{/card-default}虽然“半连接”本身是关系代数中的一个理论操作,但它在分布式数据库的查询优化中是一个核心且实用的技术。在分布式数据库中,数据存储在不同的物理节点上。当一个查询需要连接(Join)两个分别位于不同节点上的表时,最直接的(也是性能最差的)方法是:将其中一个完整表通过网络传输到另一个表所在的节点,然后进行连接操作。问题:传输整个表会产生巨大的网络开销,速度慢、成本高。解决方案:使用半连接(Semi-Join)进行优化。半连接在分布式查询优化中的应用原理目标:减少需要通过网络传输的数据量。步骤(以查询 “找出所有有订单的客户” 为例,客户表R在节点A,订单表S在节点B):投影:在节点B上,从订单表S中投影(Project)出连接键(如客户ID),得到一个很小的键值列表。传输:只将这个小列表从节点B发送到节点A。半连接:在节点A上,用这个键值列表对客户表R进行半连接过滤,只选出那些ID在列表中的客户元组。传输结果:将这些筛选后的、数量大大减少的客户元组从节点A发送回节点B。最终连接:在节点B上进行最终的完整连接,得到结果。核心思想:用一次很小的投影数据的传输,换取了避免传输整个大表的开销。半连接在这里充当了一个高效的“过滤器”。它之所以在分布式数据库中被单独提出来考,是因为:在分布式环境下,网络传输是最大的性能瓶颈。假设你要连接两个表 R(在上海)和 S(在北京):直接做法:把整个表 R 传到北京做连接 → 传输成本巨大。聪明做法(用半连接):在北京先把 S 中连接键投影出来(得到一个小结果集 K)。只把 K 传到上海。在上海用 K 对 R 做半连接,筛选出相关的 R'。把 R'(远小于 R)传到北京做最终连接。→ 传输数据量大大减少。这就是为什么在分布式数据库的考试中会出现半连接 —— 它不是理论游戏,而是解决分布式查询性能的核心优化技术。形式上,半连接可以通过自然连接和投影操作组合而成:R⋉S=πR.∗(R⋈S){dotted startColor="#ff6c6c" endColor="#1989fa"/}{card-default label="ASP(Active Server Pages)技术的基本特性" width=""}ASP是微软开发的服务器端脚本环境,用于创建动态交互式网页。依赖 Windows + IIS:需在 Windows 系统上运行,通过 IIS 解释执行,不具备跨平台性。脚本语言:通常使用 VBScript 或 JScript 编写。无需编译:脚本由服务器解释执行,无需预编译。服务器端运行:ASP 代码在服务器上执行,客户端只能看到执行后生成的 HTML 代码。源代码不暴露:ASP 源文件不会传输到客户端浏览器,保护逻辑安全客户端通过虚拟路径(URL)访问,不能用服务器物理路径直接访问。可嵌入 HTML,方便快速开发。支持通过 ADO 组件访问数据库(如 SQL Server、Access)。缺点平台锁定:仅限 Windows 环境。性能较低:解释执行效率不如编译型语言。已被淘汰:逐渐被 ASP.NET 等技术取代。ASP 是一种仅在 Windows/IIS 环境下运行的服务器端脚本技术,无需编译、代码不传客户端,用于快速开发动态网站。{/card-default}在基于 Java 的 Web 电子商务应用中,业务对象(如 JavaBean、EJB 等)通常通过 JDBC API 连接和操作数据库,实现数据持久化。JDBC 提供了与数据库无关的统一访问接口,是 Java EE 体系中的标准数据访问方案。JDBC:Java 数据库连接,是 Java Web 应用中业务对象访问数据库的标准方式,通过驱动程序与数据库交互,广泛用于电子商务等企业级应用。COM:组件对象模型,是微软的组件技术,可用于数据库访问(如 ADO),但通常与 Windows 平台绑定,不属于跨平台 Web 应用中的通用数据库访问方式。CGI:通用网关接口,是 Web 服务器与外部程序交互的早期标准,本身不是数据库访问方式,但 CGI 程序可调用其他接口(如 ODBC)访问数据库。XML:可扩展标记语言,是一种数据格式或传输协议,并非数据库访问技术。{dotted startColor="#ff6c6c" endColor="#1989fa"/}面向对象数据库(OODB)把“对象”直接存进数据库,而不是拆成表格。核心思想对象即数据:程序中的对象(类实例)可直接存入数据库,无需转换属性+方法:数据库不仅能存数据,还能存对象的方法(函数)继承与多态:支持类之间的继承关系,子类自动拥有父类特性与传统关系数据库对比关键特性对象持久化# 伪代码示例:对象直接存数据库 car = Car("Tesla", "Model 3", 2023) database.save(car) # 整个对象直接存复杂类型支持可直接存储:数组、列表、集合、嵌套对象无需拆表:一个对象的所有属性存一起继承体系 [Vehicle] △ _______|_______ | | [Car] [Truck] △ △ | | [ElectricCar] [HeavyTruck]数据库自动维护继承关系对象标识符(OID)每个对象有唯一ID,类似内存地址,用于快速定位在面向对象数据模型中,对象实例是实际创建的具体数据实体,属于模型的实例化内容,而非模型本身的抽象组成部分。模型的核心要素包括属性集合、方法集合和消息集合,它们共同定义了对象的结构和行为。因此,对象实例不属于面向对象数据模型的构成要素。对象-关系模型 是关系模型的扩展,引入了面向对象的特性,允许属性具有复杂类型,如嵌套关系、数组、结构体等。这意味着一个表的一列可以包含另一个表(嵌套关系),突破了关系模型第一范式的原子性约束。关系模型 遵循第一范式,要求所有属性必须是原子、不可再分的,不支持嵌套关系。对象-关系模型 明确支持 BLOB(二进制大对象)类型,而传统关系模型最初并不支持 BLOB,它是后来为处理多媒体数据而扩展的。对象-关系模型是融合了面向对象特征的数据模型,并非“不是数据模型”。{card-default label="通俗翻译" width=""}类之间可以具有层次结构通俗说法:“大类”可以生出“小类”,“小类”自动拥有“大类”的一切。例子:就像“交通工具”(大类)下可以有“汽车”(小类)和“飞机”(小类)。“汽车”自动拥有“交通工具”会跑、能载人的特性,同时自己还有4个轮子等新特性。结论:✅ 正确。这就是面向对象的核心思想“继承”。类内部可以具有嵌套层次结构通俗说法:一个东西里面可以套着另一个复杂的东西。例子:“电脑”这个类里面,属性不光是“价格”、“颜色”这种简单值,还可以有“CPU”(它本身又是一个类,有品牌、核心数等属性)、“内存条”(也是一个类)。电脑里面“嵌套”着CPU和内存条。结论:✅ 正确。这是面向对象数据库能处理复杂数据的关键。类的属性不能是类通俗说法:一个东西的组成部分,不能是另一个独立的东西。反例:按这个说法,“学生”这个类的“所选课程”这个属性,就不能是“课程”类(包含课程名、老师、学分等信息),只能是一串简单的文字课名。这不符合事实。正解:属性完全可以是一个类。“学生”的“所属学院”属性可以是“学院”类,“汽车”的“发动机”属性可以是“发动机”类。这正是选项B所说的“嵌套”。类包含属性和方法通俗说法:描述一个东西,既要说明它“是什么样”(数据),也要说明它能“干什么事”(功能)。例子:“电饭煲”这个类。属性(什么样):品牌、容量、颜色。方法(干什么):煮饭()、保温()、预约()这些功能。结论:✅ 正确。这是类和简单数据结构(如表格)的根本区别。{/card-default}
2026年01月28日
12 阅读
0 评论
0 点赞
2026-01-26
此内容被密码保护
加密文章,请前往内页查看详情
2026年01月26日
1 阅读
0 评论
0 点赞
1
2
3
4
...
36
0:00