操作系统课设详细解答

本文详细介绍了操作系统课程设计的三个实验,涵盖Windows和Linux平台上的进程管理。实验一涉及Windows进程的创建、观察与通信,通过VC++实现;实验二探讨Linux进程创建、新任务执行及简单的shell实现;实验三解决生产者-消费者和读者写者问题,利用互斥与同步原语。每个实验包含背景知识、设计步骤、程序流程图及实验分析,帮助读者深入理解操作系统的进程概念和并发控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

操作系统课设详细解答

一、题目一

实验一 Windows 进程管理

二、实验目的

(1)学会使用 VC 编写基本的 Win32 Consol Application(控制台应用程序)。
(2)通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解 Windows 进程的“一生”。
(3)通过阅读和分析实验程序,学习创建进程、观察进程、终止进程以及父子进程同步的基本程序设计方法。

三、总体设计

1.背景知识

Windows 所创建的每个进程都从调用 CreateProcess() API 函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。每一进程都以调用 ExitProcess() 或 TerminateProcess() API 函数终止。通常应用程序的框架负责调用 ExitProcess() 函数。对于 C++ 运行库来说,这一调用发生在应用程序的 main() 函数返回之后。

2.模块介绍

创建进程子进程startClone( )模块,主函数模块,互斥信号量的创建与释放。

3.设计步骤

(1)编写基本的 Win32 Consol Application
步骤 1:登录进入 Windows 系统,启动 VC++ 6.0。
步骤 2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 ConsolApplication”,然后在“Project name”处输入工程名,在“Location” 处输入工程目录。创建一个新的控制台应用程序工程。
步骤 3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”,然后在“File” 处输入 C/C++源程序的文件名。
步骤 4:将清单 1-1 所示的程序清单复制到新创建的 C/C++源程序中。编译成可执行文件。
步骤 5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入 Windows“命令提示符”窗口,然后进入工程目录中的 debug 子目录,执行编译好的可执行程序,列出运行结果(如果运行不成功,则可能的原因是什么?
答:路径不对或者没有编译文件等。

图1-1 一个简单的 Windows 控制台应用程序输出结果

在这里插入图片描述
(2)创建进程
本实验显示了创建子进程的基本框架。该程序只是再一次地启动自身,显示它的系统进程 ID和它在进程列表中的位置。
步骤 1:创建一个“Win32 Consol Application”工程,然后拷贝清单 1-2 中的程序,编译成可执行文件。
步骤 2:在“命令提示符”窗口运行步骤 1 中生成的可执行文件,列出运行结果。按下ctrl+alt+del,调用 windows 的任务管理器,记录进程相关的行为属性。
步骤 3:在“命令提示符”窗口加入参数重新运行生成的可执行文件,列出运行结果。按下ctrl+alt+del,调用 windows 的任务管理器,记录进程相关的行为属性。
步骤 4:修改清单 1-2 中的程序,将 nClone 的定义和初始化方法按程序注释中的修改方法进行
修改,编译成可执行文件(执行前请先保存已经完成的工作)。再按步骤 2 中的方式运行,看看结果会有什么不一样。列出行结果。从中你可以得出什么结论?说明 nClone 的作用。 变量的定义和初始化方法(位置)对程序的执行结果有影响吗?为什么?
答:控制程序执行过程,当nClone>5时跳出循环,创建子进程结束;有,在第二次更改中,由于nClone每次都初始化为0,会陷入死循环,不断创建子进程。

图1-2 创建子进程(1)

在这里插入图片描述

图1-3 创建子进程(2)

在这里插入图片描述
(3)父子进程的简单通信及终止进程
步骤 1:创建一个“Win32 Consol Application”工程,然后拷贝清单 1-3 中的程序,编译成
可执行文件。
步骤 2:在 VC 的工具栏单击“Execute Program”(执行程序) 按钮,或者按 Ctrl + F5 键,或者
在“命令提示符”窗口运行步骤 1 中生成的可执行文件,列出运行结果。
步骤 3:按源程序中注释中的提示,修改源程序 1-3,编译执行(执行前请先保存已经完成的
工作),列出运行结果。在程序中加入跟踪语句,或调试运行程序,同时参考 MSDN 中的帮助文件
CreateProcess()的使用方法,理解父子进程如何传递参数。给出程序执行过程的大概描述。
步骤 4:按源程序中注释中的提示,修改源程序 1-3,编译执行,列出运行结果。
步骤 5:参考 MSDN 中的帮助文件 CreateMutex() 、 OpenMutex() 、 ReleaseMutex() 和WaitForSingleObject()的使用方法,理解父子进程如何利用互斥体进行同步的。给出父子进程同步过程的一个大概描述。
答:CreateMutex() 创建互斥体hMutexSuicide信号、 OpenMutex()打开互斥体、 ReleaseMutex()释放互斥体、WaitForSingleObject()检测Hhandle信号状态,通过这些只允许有一个状态被创建或者使用也就是信号量唯一,实现进程同步。

图1-4父子进程的简单通信及终止进程的示例程序

在这里插入图片描述

四、详细设计

  1. 数据结构
    数组、函数调用,父子进程参数的传递、父子进程利用互斥信号进行同步、互斥体的创建、获得、检测与释放、API接口等。
  2. 程序流程图
图1-5 一个简单的 Windows 控制台应用程序流程图

在这里插入图片描述

图1-6 创建子进程流程图

在这里插入图片描述

图1-7父子进程的简单通信及终止进程的示例程序流程图

在这里插入图片描述
3. 关键代码
1-1 一个简单的 Windows 控制台应用程序

#include <windows.h> 
#include <iostream> 
#include <stdio.h>
// hello 项目
# include <iostream> 
void main() 
{ 
 std::cout << “Hello, Win32 Consol Application” << std :: endl ; 
}

1-2 创建子进程

// 创建传递过来的进程的克隆过程并赋于其 ID 值
void StartClone(int nCloneID) 
{ 
 // 提取用于当前可执行文件的文件名
 TCHAR szFilename[MAX_PATH] ; 
 GetModuleFileName(NULL, szFilename, MAX_PATH) ; 
 
 // 格式化用于子进程的命令行并通知其 EXE 文件名和克隆 ID 
 TCHAR szCmdLine[MAX_PATH]; 
 sprintf(szCmdLine,"\"%s\" %d",szFilename,nCloneID); 
 // 用于子进程的 S
### 进程调度示例代码 以下是基于常见进程调度算法(如先来先服务、时间片轮转和优先级调度)的 Java 和 C 示例代码。 #### 先来先服务 (FCFS) 调度算法 - Java 实现 ```java import java.util.*; public class FCFS { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Enter number of processes: "); int n = scanner.nextInt(); Process[] processes = new Process[n]; for(int i = 0; i < n; i++) { System.out.println("Process " + (i+1)); System.out.print("Arrival Time: "); int arrivalTime = scanner.nextInt(); System.out.print("Burst Time: "); int burstTime = scanner.nextInt(); processes[i] = new Process(i+1, arrivalTime, burstTime); } Arrays.sort(processes, Comparator.comparingInt(p -> p.arrivalTime)); int currentTime = 0; for(Process process : processes){ if(currentTime < process.arrivalTime){ currentTime = process.arrivalTime; } process.completionTime = currentTime + process.burstTime; process.turnaroundTime = process.completionTime - process.arrivalTime; process.waitingTime = process.turnaroundTime - process.burstTime; currentTime += process.burstTime; } double avgWaitingTime = Arrays.stream(processes).mapToInt(p -> p.waitingTime).average().orElse(0); double avgTurnaroundTime = Arrays.stream(processes).mapToInt(p -> p.turnaroundTime).average().orElse(0); System.out.printf("\nAverage Waiting Time: %.2f\n", avgWaitingTime); System.out.printf("Average Turnaround Time: %.2f\n", avgTurnaroundTime); System.out.println("\nP_ID\tAT\tBT\tCT\tTAT\tWT"); for(Process process : processes){ System.out.println(process.toString()); } } } class Process{ int id; int arrivalTime; int burstTime; int completionTime; int turnaroundTime; int waitingTime; public Process(int id, int arrivalTime, int burstTime){ this.id = id; this.arrivalTime = arrivalTime; this.burstTime = burstTime; } @Override public String toString(){ return String.format("%d\t%d\t%d\t%d\t%d\t%d", id, arrivalTime, burstTime, completionTime, turnaroundTime, waitingTime); } } ``` 此代码实现了先来先服务调度算法,其中 `Process` 类表示每个进程的信息[^1]。 --- #### 时间片轮转 (Round Robin) 调量算法 - C 实现 ```c #include<stdio.h> struct Process { int pid; int at; int bt; int rt; }; void findWaitingTime(struct Process proc[], int n, int wt[]) { wt[0] = 0; for (int i = 1; i < n ; i++ ) wt[i] = proc[i-1].bt + wt[i-1]; } void findTurnAroundTime(struct Process proc[], int n, int wt[], int tat[]) { for (int i = 0; i < n ; i++) tat[i] = proc[i].bt + wt[i]; } void findavgTime(struct Process proc[], int n, int quantum) { int wt[n], tat[n], total_wt = 0, total_tat = 0; findWaitingTime(proc, n, wt); findTurnAroundTime(proc, n, wt, tat); printf("Processes Burst time Waiting time Turn-around time\n"); for (int i=0;i<n;i++) { total_wt = total_wt + wt[i]; total_tat = total_tat + tat[i]; printf(" %d \t\t %d \t %d \t\t %d\n",proc[i].pid , proc[i].bt,wt[i],tat[i]); } printf("Average waiting time = %f",(float)total_wt / (float)n); printf("Average turn around time = %f",(float)total_tat / (float)n); } void roundRobin(struct Process proc[], int n, int quantum) { int rem_bt[n]; for (int i = 0 ; i < n ; i++) rem_bt[i] = proc[i].bt; int t = 0; while (1) { int done = 1; for (int i = 0 ; i < n; i++) { if (rem_bt[i] > 0) { done = 0; if (rem_bt[i] > quantum) { t += quantum; rem_bt[i] -= quantum; } else { t += rem_bt[i]; rem_bt[i] = 0; printf("Process [%d] completed at time %d\n", proc[i].pid, t); } } } if (done == 1) break; } } int main() { struct Process proc[] = {{1, 0, 8}, {2, 0, 4}, {3, 0, 9}}; int n = sizeof(proc)/sizeof(proc[0]); int quantum = 2; roundRobin(proc, n, quantum); return 0; } ``` 上述代码展示了如何使用时间片轮转法管理多个进程的任务调度过程[^2]。 --- #### 优先级调度算法 - Python 实现 ```python class Process: def __init__(self, pid, priority, burst_time): self.pid = pid self.priority = priority self.burst_time = burst_time self.remaining_time = burst_time def priority_scheduling(processes): current_time = 0 remaining_processes = sorted(processes, key=lambda x: x.priority) for process in remaining_processes: print(f"Executing P{process.pid}") current_time += process.burst_time print(f"P{process.pid} finished at time {current_time}") if __name__ == "__main__": processes = [ Process(pid=1, priority=3, burst_time=10), Process(pid=2, priority=1, burst_time=1), Process(pid=3, priority=2, burst_time=2) ] priority_scheduling(processes) ``` 这段代码演示了基于优先级的进程调度逻辑[^3]。 --- ### 常见问题解答 为了更好地理解进程调度及其应用,可以参考以下相关内容:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rothschildlhl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值