news 2026/10/15 4:11:38

操作系统实验95分:Linux信号通信、进程调度与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
操作系统实验95分:Linux信号通信、进程调度与避坑指南

简介:西南交通大学操作系统实验报告(评分A,95分)面向软件工程专业学生,覆盖Linux系统认知、Shell与常用命令、C语言编译调试,以及/proc内核信息观测等实验内容,适合需要参考完整报告写法、梳理操作系统知识点的学习者。压缩包内含1个docx文档,约1.48MB,从封面、目录到实验总结一应俱全,实验1至实验4分别涉及Linux环境、软中断通信、进程调度与线程同步,重点展示了vi/gedit编辑器、gcc/gdb工具链、meminfo与loadavg编程观测、FCFS与RR策略验证等细节。已有401人学习下载,报告结构清晰、步骤详实,尤其对目录结构、实验步骤与总结角度有完整呈现;可借此了解高分实验报告的排版组织方式,也能快速定位关键命令、代码调试思路和内核信息获取方法,为课程实验、备考复习或报告撰写提供直观参考。

1. 一份95分的操作系统实验报告:它真正能帮你什么

操作系统实验课最容易出现的情况是:代码能跑,但报告交上去只有B;代码跑通了还能把原理讲清楚,才可能拿到A。手头这份《操作系统实验报告(HXP版)》总评A、95分,来自某高校软件工程专业,七个实验从Linux环境搭建、/proc文件观测、软中断通信、FCFS/RR调度、线程同步到内存管理与缺页统计全部落地,连虚拟机网络选型、vim改名、IDE里没有fork()这种新手必然会撞的坑都记录在案。适合三类人:正在修操作系统课、想对照高分标准补齐实验报告的;准备考研或复试、需要把信号和调度机制讲明白的;以及刚转Linux、想抄一份可复现操作清单的。

2. Linux环境与/proc观测:目录、Shell与四个内核状态文件

2.1 环境准备:目录结构是理解Linux的第一张地图

报告第一个实验要求熟悉Linux界面和目录结构,看似基础,实际是后面所有实验的地基。Windows按盘符组织文件,Linux是单根树状结构:/bin放最常用的命令,/home是用户主目录,/opt放额外安装的软件,/lib是C编译器需要的库,/tmp是临时文件存放点,/proc则比较特殊——它不占磁盘空间,是内核实时状态在文件层面的映射。很多同学第一次进/proc会困惑,为什么这些文件大小都是0,因为里面的cpuinfo、meminfo、stat、uptime只有在read时才会真正生成内容。

Shell操作从四个命令开始就够用:cd负责切换目录,ls查看当前目录内容,ps列出进程状态,chmod改文件权限。报告里特别提到redirect和pipe机制,这两个才是让CLI比图形界面高效的真正原因。当时实验里第一个让我觉得“命令行确实好用”的场景,是下面这行组合命令:

ps -ef | grep test > running.txt cat running.txt

逻辑说明:ps -ef把系统里所有进程的完整信息打出来,grep test过滤出命令行里带test的进程,管道符|把前一个命令的输出作为后一个命令的输入,大于号>是重定向,把最终过滤结果写入running.txt。整个过程不用打开任何窗口,一条命令同时用到了管道和重定向两种机制。参数说明:-e表示显示所有进程,-f表示完整格式输出,grep后面跟的是过滤关键字,换成你的程序名即可。这条命令在后面调试fork代码时几乎是必需品,父进程、子进程、孙进程的PID一眼就能对比出来。

2.2 用C语言观测/proc四个状态文件

实验要求“编程实现对meminfo、loadavg、interrupts、filesystem的观测”,常见做法就是把/proc下的文件当作普通文本文件来读。写一个C程序,用fopen打开、fgets逐行读取,把结果打印到终端:

// 读取 /proc/loadavg 与 /proc/meminfo,打印核心字段 #include <stdio.h> #include <stdlib.h> int main(void) { FILE *fp; char line[128]; // loadavg:三个浮点负载值 + 活跃进程数/总进程数 + 最近运行的进程号 fp = fopen("/proc/loadavg", "r"); if (fp == NULL) { perror("open loadavg"); return 1; } fgets(line, sizeof(line), fp); printf("loadavg: %s", line); fclose(fp); // meminfo 里前几行,包含 MemTotal、MemFree、MemAvailable fp = fopen("/proc/meminfo", "r"); if (fp == NULL) { perror("open meminfo"); return 1; } for (int i = 0; i < 5; i++) { if (fgets(line, sizeof(line), fp) == NULL) break; printf("%s", line); } fclose(fp); return 0; }

逻辑说明:loadavg那一行里的三个浮点数分别是1分钟、5分钟、15分钟的平均负载,数字越大说明系统越忙;meminfo里的MemTotal是物理内存总量,MemFree是未分配内存,MemAvailable是实际可分配内存,三者差距能看出系统内存是否吃紧。参数说明:perror在文件打开失败时打印系统错误原因并返回1退出,for循环限制只打印前5行,避免整文件输入刷屏。

/proc下面值得观察的还不止这两个。/proc/cpuinfo里能看到model name和cpu MHz,/proc/version里直接写着内核版本和gcc版本,这份报告当时的实验环境是Red Hat系列发行版,内核3.10、gcc 4.8.5。/proc/stat文件第一行是cpu开头的那串数字,分别对应用户态时间、内核态时间、空闲时间等,是计算CPU占用率最原始的素材。/proc/uptime第一个数就是系统开机至今的秒数。把这些文件全部读一遍,Linux系统的运行状态基本就有概念了。

2.3 gcc与gdb:从vi写代码到断点定位的完整路径

报告里写“用vi编辑源文件,gcc编译,能跑就交”,但评分到A的实验通常多了一步gdb调试。当年我也嫌Linux下没有图形IDE不方便,在Windows里写代码再传进虚拟机,结果IDE直接报错fork()未定义,折腾半天才明白是平台API差异。后来老实按vi加gcc加gdb的流程走,反而顺手。vi部分只需要记住:i进入编辑模式,ESC退回一般模式,:wq保存退出,:w new_filename可以另存为,列几个常用gdb命令:

gdb命令作用
gcc -g -o test test.c带调试信息编译
gdb ./test进入调试器
break 15在第15行设置断点
run运行程序到断点
print x查看变量x的值
next / step单步执行,step会进入函数内部
continue继续运行到下一个断点
bt查看函数调用栈

参数说明:-g选项必须带上,否则gdb里看不到源码行号和变量名;break后面可以跟行号、函数名或文件名:行号。这里有一个大多数教材不讲的细节:fork创建子进程后,gdb默认只跟踪父进程,想跟进子进程分支需要在进入fork之前先执行set follow-fork-mode child,否则你会在子进程的断点处直接跳过。这个参数在调试软中断通信实验时非常关键。

报告总结里还提到一个值得记的底层机制:Linux内核用jiffies变量记录时间,每过一个节拍加1,开机时基准时间来自RTC硬件。用gdb单步跟进程,你会发现所有时间相关逻辑最终都落在这个计数器上。这不是考试重点,但理解了它,/proc/uptime为什么是秒数、进程调度里时间片怎么计算,心里就有底了。

3. 软中断通信:signal、fork与kill的父子进程协作

3.1 实验一:父进程创建两个子进程,Ctrl+\终止全链路

实验内容很直接:一个父进程创建两个子进程,键盘按Ctrl+\向父进程发送SIGQUIT信号,父进程收到后再通知两个子进程结束。报告里的核心代码可以原样复现,先看实验一:

#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void waiting(); void stop(); int wait_mark; int main() { int p1, p2; // 创建第一个子进程 p1,fork 返回 -1 表示创建失败,重试 while ((p1 = fork()) == -1) ; if (p1 > 0) { // 父进程分支 printf("parent process is %d \n", getpid()); while ((p2 = fork()) == -1) ; // 创建第二个子进程 p2 if (p2 > 0) { wait_mark = 1; signal(SIGQUIT, stop); // 捕获 Ctrl+\ 触发的 SIGQUIT waiting(); // 忙等直到 wait_mark 被清零 kill(p1, 16); // 向 p1 发送结束信号 16 kill(p2, 17); // 向 p2 发送结束信号 17 wait(0); wait(0); printf("\n parent process %d is killed!\n", getpid()); exit(0); } else { // 子进程 p2 分支 printf("child P2 process %d is created by %d \n", getpid(), getppid()); signal(SIGQUIT, SIG_IGN); // 子进程忽略 SIGQUIT wait_mark = 1; signal(17, stop); // 接收信号 17 后将自己置为结束 waiting(); lockf(1, 1, 0); // 锁定标准输出,防止抢行 printf("\n child P2 process %d is killed by parent %d ", getpid(), getppid()); lockf(1, 0, 0); // 解锁 } } else { // 子进程 p1 分支 printf("child P1 process %d is created by %d \n", getpid(), getppid()); signal(SIGQUIT, SIG_IGN); wait_mark = 1; signal(16, stop); // 接收信号 16 后将自己置为结束 waiting(); lockf(1, 1, 0); printf("\n child P1 process %d is killed by parent %d ", getpid(), getppid()); lockf(1, 0, 0); } return 0; } void waiting() { while (wait_mark != 0) ; // 忙等待标志位 } void stop() { wait_mark = 0; }

逻辑说明:fork的返回值语义是父进程拿到子进程PID、子进程拿到0,所以p1 > 0判断的是父进程分支,p1 == 0则进入子进程分支。P1和P2都把自己的SIGQUIT设成SIG_IGN忽略,只有父进程用signal(SIGQUIT, stop)接管了这个信号。按下Ctrl+\后,父进程的stop函数把wait_mark置0,waiting()那个自旋循环退出,接着父进程调用kill向两个子进程发信号,子进程收到后同样把wait_mark置0,结束打印。wait(0)在父进程里等两个子进程都变成僵尸并被回收,然后父进程自己也退出。

参数说明:signal函数的第一个参数是信号编号,第二个是处理函数指针或SIG_IGN;kill函数的第一个参数是目标进程PID,第二个是信号编号。这里有一个很值得注意的点:子进程P1注册的是signal(16, stop),P2注册的是signal(17, stop),而父进程发信号时kill(p1, 16)、kill(p2, 17),看起来是对应的。但报告代码注释里把kill(p2, 17)写成“send signal 16 to end the child2 process p2”,注释和实际编号对不上。x86 Linux里16号是SIGSTKFLT、17号是SIGCHLD,拿它们当自定义信号用不是不行,但SIGCHLD本身有“子进程状态变化通知父进程”的语义,覆盖掉它会让代码行为变得很不透明,这一点在后面避坑章节还会展开。

3.2 实验二:三代进程链式传递信号

实验二要求父进程只创建一个子进程,子进程再创建一个孙进程,Ctrl+\触发后按孙进程、子进程、父进程的顺序依次终止。代码结构是一个嵌套fork:

#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void waiting(); void stop(); int wait_mark; int main() { int p1; while ((p1 = fork()) == -1) ; if (p1 > 0) { // 父进程 printf("\n parent is %d\n", getpid()); wait_mark = 1; signal(SIGQUIT, stop); waiting(); kill(p1, 16); // 把结束信号传给子进程 wait(0); printf("\n parent process is killed \n"); exit(0); } else { // 子进程再 fork 一个孙进程 while ((p1 = fork()) == -1) ; if (p1 > 0) { printf("child P1 process %d is created by the parent %d \n", getpid(), getppid()); signal(SIGQUIT, SIG_IGN); wait_mark = 1; signal(16, stop); waiting(); kill(p1, 16); // 子进程把信号继续往下传 wait(0); lockf(1, 1, 0); printf("\n child P1 process %d is killed by parent %d \n", getpid(), getppid()); lockf(1, 0, 0); exit(0); } else { printf("grandson process %d is created by the parent %d \n", getpid(), getppid()); signal(SIGQUIT, SIG_IGN); wait_mark = 1; signal(16, stop); waiting(); lockf(1, 1, 0); printf("\n grandson process %d is killed by parent %d \n", getpid(), getppid()); lockf(1, 0, 0); exit(0); } } return 0; } void waiting() { while (wait_mark != 0) ; } void stop() { wait_mark = 0; }

逻辑说明:父进程收到SIGQUIT后kill(p1, 16)通知子进程;子进程在waiting()退出后继续往下走,再kill(p1, 16)把同样的信号传给孙进程;孙进程收到信号后先打印结束信息并exit(0),子进程的wait(0)立即回收它,然后子进程打印并退出,最后父进程的wait(0)回收子进程。整个链路靠每一层的wait(0)保证了严格的后代先于祖先终止。

参数说明:这个版本里所有进程共用信号16作为结束信号,逻辑上比实验一那种两个子进程用不同编号更清晰。wait_mark是全局变量,信号处理函数里改它、主循环里读它,属于课程实验最常用的进程间协作方式。它的缺点是waiting()本质是忙等待,CPU会空转,工程上更合理的做法是改用sigsuspend或pause阻塞等待信号,但在只有几个进程的实验场景里,自旋写法胜在直观。

3.3 信号参数说明与改造建议

两个实验跑完,对信号机制应该形成一张表:

信号编号默认行为本次实验中的角色
SIGINT2终止进程未使用,Ctrl+C触发
SIGQUIT3终止并生成核心转储Ctrl+\触发,父进程接管
SIGUSR110终止进程可作自定义通信信号
SIGUSR212终止进程可作自定义通信信号
16/1716/17含义随系统而异被当作自定义信号用

实验里用16和17当“自定义信号”能跑通,但这两个编号在大多数Linux发行版上有明确归属,其中17号SIGCHLD的默认语义是通知父进程“你的某个子进程状态变了”。把它改造成结束标志,相当于把系统原本的进程通知机制换掉了,代码可读性差,换到别的发行版还可能行为不一致。我会建议改成SIGUSR1和SIGUSR2,这两个编号就是专门留给应用层自定义的,kill(p1, SIGUSR1)一写,意图清晰也不需要查编号表。

另外要注意signal的注册时机。子进程必须在使用kill之前完成signal注册,否则信号先到、处理函数还没挂上,默认行为直接终止子进程,你就观察不到“子进程打印结束信息再退出”的过程。这个时序问题在实验里不出现是因为test代码都在fork之后马上注册,但自己改写成其他流程时很容易踩。

4. 进程调度与内存管理:FCFS、RR与缺页统计的实验落点

4.1 FCFS与RR:时间片、周转时间与带权周转时间

实验3要求验证FCFS和RR两种调度策略。FCFS是先来先服务,实现上只需要维护一个按到达时间排序的队列,核心是记录每个进程的到达时间、服务时间、开始时间和完成时间。RR则是在FCFS基础上加时间片轮转,时间片用完但进程还没结束就重新排到队尾。先看FCFS的模拟骨架:

#include <stdio.h> #define MAX 5 typedef struct { int pid; // 进程号 int arrive; // 到达时间 int service; // 服务时间 int start; // 首次被调度时间 int finish; // 完成时间 } PCB; // 按到达时间顺序将进程投入运行,逐项计算完成时间 void fcfs(PCB p[], int n) { int cur = 0; // 当前时间轴 for (int i = 0; i < n; i++) { if (cur < p[i].arrive) // 进程还没到,时间轴跳到到达时刻 cur = p[i].arrive; p[i].start = cur; p[i].finish = cur + p[i].service; cur = p[i].finish; } }

逻辑说明:cur是调度器当前走到的时间点;如果进程到达时间晚于cur,说明CPU空闲了一段时间,时间轴直接跳到arrive;finish减去arrive就是周转时间,周转时间除以service就是带权周转时间,这两个指标是验证调度算法优劣的度量标准。参数说明:service必须是非负整数,arrive允许为0(表示进程在0时刻全部就绪),n不能超过MAX,数组按arrive排序后传入这个函数即可。

RR的实现思路跟FCFS区别在就绪队列的出入队逻辑:每个进程维护一个剩余服务时间remaining,执行时取队首,运行时间取min(时间片, remaining),时间片用完还没跑完就重新放回队尾。实验报告里验证的结果是:时间片越长,RR的平均周转时间越接近FCFS;时间片过短,上下文切换开销会明显增大。这个结论自己动手模拟并不难验证。

调度算法平均周转时间平均带权周转时间适用场景
FCFS长,受长进程拖累波动大批处理系统
RR(时间片适中)中相对稳定交互式系统
RR(时间片过小)短但切换开销大不稳定几乎不适用

4.2 页面置换与缺页统计:LRU模拟与/vmstat后验

实验7的标题是系统缺页次数统计,常见的落地做法有两条路:一种是直接读/proc/vmstat里的pgfault和pgmajfault字段,配合系统调用来统计一次程序执行引发的缺页次数;另一种是自写页面置换模拟器,用固定引用串验证FIFO、LRU、OPT三种算法的缺页差异。后者更适合写进实验报告,因为能产生对比数据。LRU的朴素实现可以这样写:

// LRU 模拟:3 个物理块,依次处理引用串 int page[] = {1,2,3,4,1,2,5,1,2,3,4,5}; int frames = 3; int lru_frame[3]; // 当前驻留页面 int lru_age[3]; // 老化计数,值越大表示越久未被访问 int page_faults = 0; for (int i = 0; i < 12; i++) { int hit = 0; for (int j = 0; j < frames; j++) { if (lru_frame[j] == page[i]) { hit = 1; lru_age[j] = 0; // 刚被访问,年龄清零 } else { lru_age[j]++; // 其他页年龄加 1 } } if (!hit) { // 缺页:淘汰年龄最大的页 int victim = 0; for (int j = 1; j < frames; j++) if (lru_age[j] > lru_age[victim]) victim = j; lru_frame[victim] = page[i]; lru_age[victim] = 0; page_faults++; } }

逻辑说明:每次访问一个页时,命中的页面age清零、其余页面age加1;缺页时找age最大的物理块淘汰,这正好模拟了LRU的“淘汰最久未使用”原则。参数说明:frames可以改成4或5观察缺页次数变化;page数组换成其他引用串即可得到不同结果;lru_age数组要初始化为0,同时lru_frame初始化为-1表示空块。工程上的LRU不会用这种遍历数组的方式实现,而会用哈希表加双向链表做到O(1),但课程验证性实验里数组模拟更能看清原理。

用上面这个经典引用串在3个物理块下做测试:FIFO缺页9次,LRU缺页10次,OPT缺页7次。这个结果本身就是很好的讨论素材——LRU并不是最优,但它在没有未来知识的情况下更稳定;FIFO甚至可能出现Belady异常,即物理块增加缺页反而增多。报告中只填“结果展示”段,没有解释为什么LRU会比FIFO差,这一手可以在答辩时补上。

4.3 线程同步:信号量与互斥锁的边界

实验4线程同步在报告正文里只给了实验目的和步骤,没有贴代码,但这是最容易在答辩环节被追问的部分。常见做法是拿两个线程对同一个全局计数器做加法,一个用互斥锁保护,一个不加锁,对比最终值。代码片段:

#include <pthread.h> int counter = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void *worker(void *arg) { for (int i = 0; i < 100000; i++) { pthread_mutex_lock(&mutex); counter++; pthread_mutex_unlock(&mutex); } return NULL; }

逻辑说明:两个线程同时跑worker,pthread_mutex_lock保证同一时刻只有一个线程进入临界区,counter++不会互相覆盖。如果不加锁,counter最终值会小于200000,因为counter++不是原子操作,它对应“读-改-写”三步,两个线程可能同时读到同一个值再写回去,丢一次递增。参数说明:PTHREAD_MUTEX_INITIALIZER是静态初始化的互斥锁,适用场景是全局锁;如果锁是局部变量,要改用pthread_mutex_init。

线程同步和进程同步的区别在信号量部分更明显。sem_wait减计数、sem_post加计数,适合解决生产者消费者问题;mutex是锁语义,只有持有和释放两种状态。实验中很多同学把mutex当信号量用,逻辑上能跑,但概念上就是混了:mutex必须由持有它的线程释放,信号量可以由任意进程增加计数。这两者的差别,面试时往往是区分“真做过实验”和“背过答案”的问题。

5. 实验避坑:四条高频踩坑记录与排查顺序

5.1 Windows下写fork()代码,IDE直接报错

现象:在Windows的IDE里写完C代码,ftp传到Linux虚拟机后一头雾水,因为IDE根本提示fork()未定义,代码在本地也编译不过。

原因:fork是POSIX接口,Windows进程创建走的是CreateProcess,两者不是同一套API。IDE报错不是代码问题,是平台问题。

解决:不要在Windows里写完整代码再传虚拟机。直接在Linux的vi里写,写完gcc编译,报错当场改,反而节省时间。如果非要传文件,用scp传源码文件而不是粘贴大段代码,编码问题会少很多。

5.2 虚拟机网络连不上,三种网络模式选错

现象:虚拟机装好后网络连接一直失败,ping不通外网,apt或yum也没法用。

原因:虚拟网络适配器模式选错了。桥接模式相当于把虚拟机直接插到局域网交换机上,IP容易和宿主机网段里的其他设备冲突;host-only模式虚拟机与外部网络完全隔离;NAT模式通过宿主机的地址转换访问外部网络,是默认情况下最稳的选择。

解决:大部分操作系统实验不需要外部网络,但需要软件源安装gdb等工具,所以建议直接用NAT模式。桥接模式虽然能实现虚实互访,但一旦网段里设备多起来,IP冲突的概率不小,实验过程中断网排查会非常花时间。这一点报告里也记录了同样的结论,属于新手必踩的高频坑。

5.3 kill(p2, 17)与signal(16, stop)对不上

现象:实验一中P2子进程没按预期结束,或者父进程wait()返回异常,调试时发现代码注释写的是send signal 16,实际kill发送的却是17。

原因:报告原始代码里存在编号不一致的情况,而且17号信号在x86 Linux环境下是SIGCHLD,覆盖它的处理函数会干扰父子进程状态通知机制。代码能跑是因为信号编号在系统层面合法,但行为不可控。

解决:自定义信号别用16和17这种有明确语义的编号。改成SIGUSR1和SIGUSR2,代码写成kill(p2, SIGUSR1),语义一目了然,也彻底绕开SIGCHLD的干扰。线信号机制时要特别注意注册和发送的编号一致性,最好把信号宏名写到注释里。

5.4 父子进程打印顺序乱掉

现象:按Ctrl+\后,两个子进程的结束信息打印顺序跟预期相反,或者输出挤在一行里。

原因:printf是带缓冲的,父子进程共享同一个终端输出,两个进程同时打印时没有同步机制,系统调度顺序又无法预测,输出自然乱序。

解决:报告里用的lockf(1, 1, 0)加锁、lockf(1, 0, 0)解锁就是针对这个问题的。也可以用fflush(stdout)强制刷新缓冲区,或者改用write(STDOUT_FILENO, ...)这种无缓冲的系统调用。输出顺序这个事情看起来小,但在实验报告截图里最影响观感,值得花一分钟处理。

5.5 想在Linux里装图形IDE,折腾一晚上

现象:感觉没有IDE就没有安全感,在Linux里装了好几个IDE,没搞成,实验也没推进。

原因:图形IDE在虚拟机里往往依赖一大堆运行库,装起来费时,而且对实验主体帮助不大。vi加上gcc加上gdb,已经完全覆盖本课程的实验需求。

解决:教学实验里,vi写代码、gcc编译、gdb调试,是效率最高的链路。等哪天要写大型项目再考虑IDE不迟。报告总结里也写了“直接在linux中验证,果然也没什么问题”,新手阶段命令行工具链完全够用。

6. 把报告变成面试弹药:系统调用与缺页中断的后验方法

6.1 系统调用实验的验证技巧

实验6要求写系统调用,报告的验证方法停留在“运行成功截图”这一步。真正在复试或面试里讲清楚这个实验,需要一条后验路径:用strace观察一个程序到底触发了哪些系统调用。

strace -e trace=open,read cat /proc/uptime 2>&1 | head -20

逻辑说明:cat命令打开/proc/uptime并读取内容,strace会打印出open和read这两个系统调用的完整参数和返回值,能看到文件描述符、读取字节数等细节。参数说明:-e trace=open,read只跟踪open和read,避免输出刷屏;2>&1是把strace的stderr输出合并到stdout,不然管道过滤不到。

6.2 缺页与页面置换的手算验证

缺页次数统计这种实验,别人问起来最有效的办法是当场手算一组数据。用前面那段引用串,帧数为3时,FIFO、LRU、OPT的缺页次数分别是9、10、7。面试官往往不只想要数字,更想听你怎么解释为什么LRU不是最优。回答思路是:LRU依据的是历史的局部性,OPT依据的是未来的知识,前者无法预知一个页到底还要多久才会被访问,所以在某些串上反而比FIFO差。

算法缺页次数(3帧)是否需要未来知识
FIFO9否
LRU10否
OPT7是

6.3 从报告到讲稿:三个问题自测

这份报告拿在手里,不建议死背结论。合上报告,试着回答三个问题:信号16和17在Linux里到底是什么?FCFS和RR的周转时间为什么在不同时间片下差异这么大?缺页统计到底是统计谁、在哪里统计?三个问题都能不看资料讲清楚,实验就真正是你的了。整理好的实验报告压缩包里包含七个实验的正文、核心代码、结果截图与个人声明,按自己学校的实验要求改一改就能用。

那次因为没先用strace确认信号到达就直接交实验,后续补验证花了一个晚上。从那以后,我每次写完带fork和signal的代码,都强制自己先跑一版strace确认信号确实到了对应进程,再继续往下做实验。希望帮到你。

本文还有配套的精品资源,点击获取

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

操作系统期末真题这样用:拆考点、定顺序、抓重点

简介&#xff1a;操作系统课程的期末试题与答案解析&#xff0c;出自西安电子科技大学&#xff0c;面向计算机相关专业本科生&#xff0c;可作为考前冲刺、考研基础巩固与自学自测材料。试卷为闭卷&#xff0c;限时一百二十分钟&#xff0c;满分一百分&#xff0c;包含选择题、…

作者头像 李华
网站建设 2026/10/15 4:10:50

金蝶云星空V7.3生产管理培训笔记:流程与坑位全解析

简介&#xff1a;金蝶云星空V7.3产品培训_制造_生产管理PPT&#xff0c;面向制造企业生产管理人员、ERP实施顾问及系统学习者&#xff0c;系统讲解从生产计划、投料领料、生产汇报到产品入库、订单结案的全过程监督与控制方法。压缩包内为1个PPTX演示文稿&#xff0c;约5.28MB&…

作者头像 李华
网站建设 2026/10/15 4:10:45

巴法禄全空气系统10问深度解析:送风、过滤、除湿与运行表现

全空气系统通过风管将经过处理的空气送入不同房间&#xff0c;能够把温度调节、空气输送、过滤和部分湿度控制集中到一套系统中。巴法禄水牛变频全空气室内机采用多点送风、高效过滤、直流无刷EC风机等设计&#xff0c;并可配置光氢离子杀菌模块、负离子发生器及再热盘管等功能…

作者头像 李华
网站建设 2026/10/15 4:10:33

PAN-OS V9.0管理员实战:策略NAT与日志排查全解析

简介&#xff1a;Palo Alto Networks官方发布的《PAN-OS管理员指南》V9.0中文版&#xff0c;面向防火墙管理员与网络安全运维工程师&#xff0c;旨在帮助读者快速掌握PAN-OS平台的部署配置与日常管理方法&#xff0c;尤其适合刚接触PA系列防火墙、需要查阅官方操作细节的用户。…

作者头像 李华
网站建设 2026/10/15 4:09:39

意识作为整体性感知集合| 赵杰 | 量子感知论

作者&#xff1a;赵杰清华大学硕士、微美全息云科技&#xff08;NASDAQ&#xff1a;WIMI&#xff09;董事长、微算法科技&#xff08;NASDAQ&#xff1a;MLGO&#xff09;董事长、育杰奖学金创始人赵杰提出的核心命题&#xff1a;意识就是对整体性的感知的集合&#xff1b;这种…

作者头像 李华
网站建设 2026/10/15 4:09:38

请叫我「艾欧同学」!✨

吃完 Token&#xff0c;该去上学了&#xff01;&#x1f392; 听说有人说我只会吃 Token&#xff1f; 等我学完…… 再也不许有人说我白吃 Token&#xff01;&#x1f624; 艾欧同学的 AGI 学习旅程 正式开启&#xff01;✨#AI新手村 #数字造梦季 #用二次元开启AGI之旅 #开启未…

作者头像 李华