操作系统课程实验指导书

操作系统课程实验指导书

适用专业:计算机类相关专业

***

计算机学院

20##4


目录

操作系统课程实验指导书... 1

目录... 2

一、课程实验基本目的与可能收获... 3

二、课程实验基本要求... 4

三、课程实验项目... 5

1、项目一: Windows进程管理管理工具;设备管理工具;磁盘、目录和文件管理工具的使用(2学时) 5

2、项目二:模拟实现进程互斥和同步的信号量机制(6学时) 5

3、项目三:模拟实现进程调度算法(4学时) 8

4、项目四:模拟实现磁盘调度算法(4学时) 9

四、课程实验过程与具体要求... 11

五、课程实验交付成果说明... 12

六、考核方式及成绩评定方法... 14

七、主要参考文献与网址... 15

附录A 部分课程实验题目参考源程序... 16

A.1  读者写者问题参考源程序... 16

A.2  进程调度算法参考源程序... 25

A.3  磁盘调度算法参考源程序... 42

附录B软件开发文档指南... 60


一、课程实验基本目的与可能收获

1、学习《操作系统》要求理论与实践相结合,本门实验课程是对《操作系统》课堂教学的一个重要补充,与理论学习起着相辅相成的作用,是实施《操作系统》教学的一个重要组成部分。通过本实验课的实践学习,可以增强本专业的学生对系统实现的认识。对加深理解和掌握操作系统相关原理有重要帮助。进一步提高学生综合运用所学专业知识分析和解决实际应用问题的能力,提高实际动手编程的能力,为日后从事计算机软硬件开发工作打下坚实基础。

2、通过课程实验的实践及其前后的准备与总结,复习、领会、巩固和运用课堂上所学的知识和方法,提升分析问题,解决问题的实际能力。

3、使学生通过开发实践,了解项目管理、团队合作、文档编写、口头与书面表达的重要性。使每个学生了解软件工具与环境对于项目开发的重要性,并且重点深入掌握好一、两种较新或较流行的软件工具或计算机应用技术、技能。

4、通过“稍大的”富有挑战性的软件实验项目开发实践,提高学生的自学能力、书面与口头表达能力、创造能力和与团队其他成员交往和协作开发软件的能力,提高学生今后参与开发稍大规模实际软件项目和探索未知领域的能力和自信心。


二、课程实验基本要求

1、深入而直观地理解操作系统使用的各类算法,其中常见的重要算法主要包括:

⑴ 经典实现进程同步的信号量算法。

⑵ 处理机调度算法。

⑶ 常见的磁盘调度算法。

2、实验方式与基本要求:

实验方式:上机,分析,设计,测试。

基本要求:采取课内上机和业余上机相结合的方式进行,在规定时间内进行程序检查和实验报告。

⑴ 学生应当独立地完成自己所分配到的课题任务,严禁抄袭或拷贝他人的成果。

⑵ 学生能使用面向对象语言(如:Java、VC++、VB、Delphi等)完成各个实验,并且程序正确,功能完整,界面友好。

⑶ 学生在上机做实验前,应事先将程序、调试数据、上机操作顺序等准备好。

⑷ 在实验后,写出实验报告,对需要完成的任务、程序体系结构和模块结构设计、采用的调试数据、上机操作过程、实验过程遇到的问题、如何解决遇到的问题、最后实验的成果等内容进行描述。


三、课程实验项目

1、项目一: Windows进程管理管理工具;设备管理工具;磁盘、目录和文件管理工具的使用(2学时)

①、实验目的

a、熟悉Windows进程管理管理工具;设备管理工具;磁盘、目录和文件管理工具的使用。

②、实验内容

a、Windows任务管理器、资源管理器、设备管理器、系统管理工具的使用。

③、实验要求

a、实践操作。

④、运行结果

⑤、提示

⑥、分析与讨论

a、如何进行操作系统系统的优化设置?

⑦、参考代码

2、项目二:模拟实现进程互斥和同步的信号量机制(6学时)

①、实验目的

a、掌握进程并发执行的原理,及其所引起的同步、互斥问题。观察、体会操作系统的进程互斥和同步管理方法,并通过一个简单的进程互斥和同步模拟程序的实现,加深对互斥和同步算法的理解。

b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。

②、实验内容

分别用信号量来模拟实现读者优先和写者优先的读者-写者问题。(实现其中之一)。

信号量实现进程的互斥和同步。

用信号量来模拟实现读、写进程间的互斥。

设置多个读进程,例如:A\B\C和多个写进程,例如:D\E\F,由进程间互斥可以知道,哪方进程先进入,资源就由谁占用。

③、实验要求

a、使用模块化设计思想来设计。

b、给出算法的流程图或伪码说明。

c、学生可按照自身条件,随意选择采用的算法,用C语言编写出程序,实现使用信号量的互斥和同步。

④、运行结果

a、显示进程的运行轨迹和执行先后顺序。

⑤、提示

在Windows环境下,创建一个包含n 个线程的控制台进程。用这n 个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求,进行读写操作。请用信号量机制分别实现读者优先和写者优先的读者-写者问题。

读者-写者问题的读写操作限制:

1)写-写互斥;

2)读-写互斥;

3)读-读允许;

读者优先的附加限制:如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。

测试数据文件格式:

测试数据文件包括n 行测试数据,分别描述创建的n 个线程是读者还是写者,以及读写操作的开始时间和持续时间。每行测试数据包括四个字段,各字段间用空格分隔。第一字段为一个正整数,表示线程序号。第二字段表示相应线程角色,R 表示读者是,W 表示写者。第三字段为一个正数,表示读写操作的开始时间。线程创建后,延时相应时间(单位为秒)后发出对共享资源的读写申请。第四字段为一个正数,表示读写操作的持续时间。当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。

下面是一个测试数据文件的例子:

1 R 3 5

2 W 4 5

3 R 5 2

4 R 6 5

5 W 5.1 3

与实验相关的API 介绍

线程控制:

CreateThread 完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。

HANDLE CreateThread(

LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD

DWORD dwStackSize, // initial stack size

LPTHREAD_START_ROUTINE lpStartAddress, // thread

function

LPVOID lpParameter, // thread argument

DWORD dwCreationFlags, // creation option

LPDWORD lpThreadId // thread identifier

);

ExitThread 用于结束当前线程。

VOID ExitThread(

DWORD dwExitCode // exit code for this thread

);

Sleep 可在指定的时间内挂起当前线程。

VOID Sleep(

DWORD dwMilliseconds // sleep time

);

信号量控制:

CreateMutex 创建一个互斥对象,返回对象句柄;

HANDLE CreateMutex(

LPSECURITY_ATTRIBUTES lpMutexAttributes, // SD

BOOL bInitialOwner, // initial owner

LPCTSTR lpName // object name

);

OpenMutex 打开并返回一个已存在的互斥对象句柄,用于后续访问;

HANDLE OpenMutex(

DWORD dwDesiredAccess, // access

BOOL bInheritHandle, // inheritance option

LPCTSTR lpName // object name

);

ReleaseMutex 释放对互斥对象的占用,使之成为可用。

BOOL ReleaseMutex(

HANDLE hMutex // handle to mutex

);

WaitForSingleObject 可在指定的时间内等待指定对象为可用状态;

DWORD WaitForSingleObject(

HANDLE hHandle, // handle to object

DWORD dwMilliseconds // time-out interval

);

⑥、分析与讨论

a、如何理解“算法+数据结构=程序设计”?

b、如何理解“数据结构始终是为实现功能服务的”?

⑦、参考代码

参看:附录A1

3、项目三:模拟实现进程调度算法(4学时)

①、实验目的

a、进程调度是处理机管理的核心内容。观察、体会操作系统的进程调度方法,并通过一个简单的进程调度模拟程序的实现,加深对进程控制块、进程队列、进程调度算法,进程切换的理解,并体会和了解各种调度算法的具体实施办法。

b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。

②、实验内容

a、设计进程控制块PCB表结构,模拟实现进程调度算法:FIFO,静态优先级调度,时间片轮转调度,短进程优先调度算法,多级反馈队列调度。(实现其中之一个以上)。

b、编写一个进程调度程序模拟程序。模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。

c、由用户输入(可通过文件输入)进程名、进程状态、进程运行时间和进程优先级等数据。

③、实验要求

a、使用模块化设计思想来设计。

b、给出主函数和各个算法函数的流程图。

c、学生可按照自身条件,随意选择采用的算法,(例如:采用冒泡法编写程序,实现短进程优先调度的算法)。

d、进程调度程序模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。

④、运行结果

a、给出进程的调度模拟操作排序结果。

⑤、提示

a、每个进程可有三个状态,并假设初始状态为就绪状态。

b、为了便于处理,程序中的进程运行时间以纳秒为单位计算。

C、各进程的优先级或轮转时间数以及进程需运行的纳秒数的初始值均由用户给定。

d、在优先级算法中,采用静态优先级。在时间片轮转算法中,采用可变时间片,由用户给定。

e、对于遇到优先级一致的情况,采用FIFO策略解决。

f、输入:进程流文件(文本文件),其中存储的是一系列要执行的进程,每个进程包括四个数据项:进程名 进程状态(1就绪 2等待 3运行) 所需时间 优先级(0级最高)。

g、输出:进程执行流 等待时间 平均等待时间。

⑥、分析与讨论

a、各种进程调度算法的异同?

b、如何理解“算法+数据结构=程序设计”?

c、如何理解“数据结构始终是为实现功能服务的”?

⑦、参考代码

参看:附录A2

4、项目四:模拟实现磁盘调度算法(4学时)

①、实验目的

a、观察、体会操作系统的磁盘调度方法,并通过一个简单的磁盘调度模拟程序的实现,加深对磁盘调度的理解。

b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。

②、实验内容

a、模拟实现磁盘调度算法:FCFS,最短寻道优先,电梯算法(实现其中之一种以上)。

b、磁道请求服务顺序由用户输入(可通过从指定的文本文件(TXT文件)中取出)。

③、实验要求

a、使用模块化设计思想来设计。

b、给出主函数和各个算法函数的流程图。

c、学生可按照自身条件,随意选择采用的算法。

④、运行结果

a、给出磁盘调度算法模拟程序对进程寻道请求的排序结果。

输出:

第一列:磁道的服务顺序;

第二列:移动的磁道数;

最后计算出总移动磁道数、平均移动磁道数。

⑤、提示

参看:附录A3

⑥、分析与讨论

a、各种磁盘调度算法的异同?

b、如何理解“算法+数据结构=程序设计”?

c、如何理解“数据结构始终是为实现功能服务的”?

⑦、参考代码

参看:附录A3


四、课程实验过程与具体要求

1、学习研究课程实验指导书。

2、确定目标、初步方案,准备、试用开发环境与工具。

确定开发目标及初步方案;选择、准备、试用开发平台、开发设计工具及其他有关工具。

3、学习与搜集素材,借阅、购置必要的书籍与材料。

根据自己承担的任务利用各种途径(图书馆、因特网、书店、同学亲友等)进行针对性的学习并收集相关素材,包括精选、购置必要的书籍。

4、各阶段的开发工作。

开发应分阶段进行,具体安排自定。

5、做好个人的开发记录、总结,做好同学之间的交流与互助。

各个开发小组及其每个成员可以互相研讨、帮助,但必须独立完成自己承担的开发任务与文档编制任务,不得抄袭他人成果。

每个小组由小组长建立项目开发记录本(或开发日志)(不少于20页),每周至少做一次记录,包括小组会议记录,小组记录本要保存好以供老师检查。

建议每个小组成员也建立自己个人的开发记录或日志。记录的内容可以包括:个人在小组中承担任务、计划与进度;相关学科与软件工具学习内容摘要与存在问题、难点;好的创意与建议;开发或学习心得;文档草稿;重要信息与线索记录等。

这样做可以有助于项目开发工作和自己的学习和进步,也有助于最后完成个人的课程实验报告。


五、课程实验交付成果说明

1、要求:

A、书面材料

(1)个人报告(必交): 每个学生提交个人课程实验报告 (手写(运行界面可抓图),不少于5页),交给组长。由组长连同小组打印报告一并按时交给老师。

(2)小组报告(可选): 课程实验小组报告(A4打印稿,不少于10页,报告大纲由组长起草,报告要经过全组讨论,由各个成员提供素材)。

(3)小组项目开发记录本(可选):(含小组进行课程实验的活动日志与会议记录)。

B、软件与电子文档

(1)个人电子文档(必交):把含个人完成的文档交给小组负责保管文档的角色 (平时组长安排的计算机的硬盘和电子邮箱中,最后保存在不止一台计算机中)。个人U盘和电子邮箱中应当包含个人完成的开发源代码、文档和个人课程实验报告的电子文档。

(2)小组项目电子文档(必交):小组平时把运行系统的文档保存在组长安排的计算机硬盘小组项目专用目录中。完成项目后,把小组项目课程实验报告、可运行程序、源代码、相关文档连同各个小组成员的文档分别复制到在小组项目专用目录下不同的子目录以及每个成员的子目录中,待老师审查、验收。

注1、参加课程实验的小组、个人建立的文档建立目录时按照如下统一命名规则实例建立目录名,“班级子目录名/小组子目录名/个人子目录名”,比如:“20041083_s/G1张三/C_ 200410833999李四”表示:“20##级计算机科学与技术专业软件班/第1小组(组长张三)/角色C,李四,学号:200410833999”。

2、正文格式:

每个实验项目书写一份实验报告。除最后一个项目外,实验报告在下一个项目开始时上交。最后一个项目实验报告在全部实验结束后一周内上交。

实验报告的书写要求如下:

封面按以下格式书写:(居中)

《操作系统》课程实验(第 * 次)

实验课题:

姓    名:

学    号:

年级班级:

教学班级:

专业方向:

同组人:

指导教师:

实验时间:

注:专业方向包括专业名称和自己所选方向名称;实验时间如果是两次以上,写明起止时间。

报告内容:可按以下顺序书写:

1、实验名称;

2、实验目的和要求;

3、实验的软硬件环境;

4、实验内容及实验步骤;

5、实验原始记录;

(1)问题描述。包括此问题的理论和实际两方面。

(2)解决方案。包括:软硬件选择的理论与实际依据、使用算法、程序语言及不同语言可能对问题解决的影响。

(3)解决方案的流程图、主要算法的描述与具体实现的说明。

(4)具体的解决实例。包括:实际完成的程序的基本结构、程序运行结果等等。

6、实验结果分析(包括有何特点、存在的问题、改进意见等),写出心得与体会(有何感想,学到了什么?)。


六、考核方式及成绩评定方法

1、考核方式:

根据学生平时的表现态度、完成实验的情况、实验报告的完成情况、综合上机检查情况等给出每个学生的实验成绩。

2、成绩评定方法:

实验完成后,学生必须将所有资料交教师验收。包括:程序代码说明及测试报告。

然后,学生必须按规定的格式撰写实验报告,交教师审阅和评定成绩。

实验报告的成绩评定实行优秀、良好、中等、及格和不及格五个等级。

实验报告评分原则表

各次实验分数之和为总评实验成绩。优秀人数一般不得超过总人数的20%。不及格者不能得到相应的学分,需重做实验,经考核及格后方可取得相应学分。实验成绩是否折算计入期末总评成绩,以及具体折算办法,由开课同期的学校相关文件规定。


七、主要参考文献与网址

[1] 计算机操作系统(第三版),汤小丹等,西安电子科技大学出版社, 20##年5月

[2] 操作系统习题解答与实验指导,王煜、张明、刘振鹏 ,高等教育出版社, 20##年12月

[3] 操作系统原理实验,周苏、金海溶、李洁、科学出版社, 20##年12月

[4] 操作系统教程题解与实验指导,孟静,高等教育出版社, 20##年6月

[5] 操作系统教程——原理和实例分析,孟静,高等教育出版社, 20##年9月

[6] VC++深入详解,孙鑫、余安萍,电子工业出版社,20##年

[7] VC++程序设计解析与训练,祁云嵩,华东理工大学出版社,20##年

[8] 谭浩强,张基温.C/C++程序设计教程[M].北京:高等教育出版社.20##年

[9]参考网站的网址:

http://www.csdn.net

http://samples.gotdotnet.com/quickstart/

http://msdn.microsoft.com/net

http://msdn.microsoft.com/vstudio/

http://sourceforge.net/

http://www.codepub.com/ 源码网

http://www.cncode.com/ 中国源码中心

http://www.cnjavaclub.com/ 中国JAVA俱乐部

JDK (Java开发工具包)及JDK文档下载网址

http://www.oracle.com/technetwork/java/javase/overview/index.html


附录A 部分课程实验题目参考源程序

A.1  读者写者问题参考源程序

/***********************************************************************************************************

*   Source File Name :   LGY_Sigal_RW.cpp                                                                  *

*   Project Name:        LGY_Sigal_RW                                                                      *

*   Engineer:            赖国勇                                                                            *

*   Date Generated:      20##-11-04                                                                        *

*   Last Revision Date:  20##-04-11                                                                        *

*   Brief Description:                                                                                      *

*   ①、实验目的                                                                                           *

*          a、掌握进程并发执行的原理,及其所引起的同步、互斥问题。观察、体会操作系统的进程互斥和同步管理方法,*

*                   并通过一个简单的进程互斥和同步模拟程序的实现,加深对互斥和同步算法的理解。                     *

*          b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。                                      *

*   ②、实验内容                                                                                           *

*            a、分别用信号量来模拟实现读者优先和写者优先的读者-写者问题。(实现其中之一)。                     *

*         b、信号量实现进程的互斥和同步。                                                                    *

*            c、用信号量来模拟实现读、写进程间的互斥。                                                          *

*            d、设置多个读进程,例如:A\B\C和多个写进程,例如:D\E\F,由进程间互斥可以知道,哪方进程先进入,    *

*                   资源就由谁占用。                                                                               *

*     ③、实验要求                                                                                           *

*         a、使用模块化设计思想来设计。                                                                      *

*          b、给出主函数和各个算法函数的流程图或伪码说明。                                                    *

*          c、学生可按照自身条件,随意选择采用的算法,用C语言编写出程序,实现使用信号量的互斥和同步。         *

*     ④、运行结果                                                                                           *

*        a、显示进程的运行轨迹和执行先后顺序。                                                               *

*     ⑤、提示                                                                                               *

*     在Windows环境下,生成一个包含n 个线程的控制台进程。用这n 个线程来表示n个读者或写者。                   *

*     每个线程按相应测试数据文件的要求,进行读写操作。用信号量机制分别实现读者优先和写者优先的读者-写者问题。*

*                                                                                                            *

*     VC++6.0调试通过  项目类型:Win32 Console Application                                                   *

*                                                                                                          *

*                                                                                                            *

************************************************************************************************************/

#include <windows.h>

#include <ctype.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <malloc.h>

#define  MAX_PERSON   100 //并发线程的最大数量

#define  READER       0

#define  WRITER       1

#define  END         -1

#define  R            READER

#define  W            WRITER

typedef struct _Person    //线程结构体定义

{

    HANDLE m_hThread;          //线程句柄

    int    m_nType;                 //线程类型

    int    m_nStartTime;   //线程开始时间

    int    m_nRunTime;           //线程运行时间

    int    m_nID;                    //线程ID

}Person;

Person g_Persons[MAX_PERSON];     //线程结构体数组

int    g_NumPerson = 0;                   //线程数量

long   g_CurrentTime= 0;          //当前时间

int    g_PersonLists[] = {           //6个给定的线程

    1, R, 5, 5,

       2, W, 4, 5,

    3, R, 2, 2,

    4, R, 1, 5,

       5, W, 4, 3,

       6, R, 7, 7,

       END,

};

int          g_NumOfReading = 0;   //读者数量

int          g_NumOfWriting   =0;  //写者数量

HANDLE  g_hR_R_Mutex;        //读者_读者互斥对象的句柄

HANDLE  g_hW_R_Mutex;              //写者_读者互斥对象的句柄

HANDLE  g_hW_W_Mutex;             //写者_写者互斥对象的句柄

void             CheckPersonList(int *pPersonList);                   //遍历线程结构体数组,生成线程

bool             CreateReader(int iStartTime,int iRunTime); //生成读者线程

bool             CreateWriter(int iStartTime,int iRunTime); //生成写者线程

DWORD  WINAPI    ReaderProc(LPVOID lpParam);                        //指定读者线程执行的功能函数

DWORD  WINAPI    WriterProc(LPVOID lpParam);                        //指定写者线程执行的功能函数

int main()

{

    g_hR_R_Mutex = CreateMutex(NULL,FALSE,NULL);      //生成读者_读者互斥对象,返回句柄

    g_hW_R_Mutex = CreateMutex(NULL,FALSE,NULL);     //生成写者_读者互斥对象,返回句柄

    g_hW_W_Mutex = CreateMutex(NULL,FALSE,NULL);    //生成写者_写者互斥对象,返回句柄

      

       //输出线程结构体数组

       printf("\n g_PersonLists[] = {\n");

       printf("   序号  类型  开始时间  运行时间\n");

       printf("   1, R, 5, 5,\n");

       printf("   2, W, 4, 5,\n");

       printf("   3, R, 2, 2,\n");

       printf("   4, R, 1, 5,\n");

       printf("   5, W, 4, 3,\n");

       printf("   6, R, 7, 7,\n");

       printf("   END,\n");

       printf("   }\n\n");

       g_CurrentTime = 0;       //当前时间清零

       while(true)

    {

        printf("   当前时间 CurrentTime = %d\n\n",g_CurrentTime);

        CheckPersonList(g_PersonLists);   //遍历线程结构体数组,生成线程

        g_CurrentTime++;                       //当前时间+1

        Sleep(300);

    }

    return 0;

}     //int main()

void CheckPersonList(int *pPersonLists)      //遍历线程结构体数组,生成线程

{

    int  i=0;

    int  *pList = pPersonLists;         //指向线程结构体数组的指针

    bool Ret;

    while(pList[0] != END)

    {

        if(pList[2] == g_CurrentTime)      //线程开始时间等于当前时间

        {

            switch(pList[1])                   //判别线程的类型

            {

            case R:

                Ret = CreateReader(pList[2],pList[3]);  //生成读者线程

                break;

            case W:

                Ret = CreateWriter(pList[2],pList[3]);  //生成写者线程

                break;

            }

            if(!Ret)

                printf("   生成线程 %d 失败\n",pList[0]);

        }

        pList += 4; // 移动至一个线程的数据

    }

}     //void CheckPersonList(int *pPersonLists)

DWORD  WINAPI ReaderProc(LPVOID lpParam)   //指定读者线程执行的功能函数

{

      

    if(g_NumOfWriting>=1)       //现在有一个以上写者正在工作

              {

              WaitForSingleObject(g_hW_R_Mutex,INFINITE);     //用写者_读者互斥对象的句柄实现互斥

              ReleaseMutex(g_hW_R_Mutex);                               //释放写者_读者互斥对象的句柄

              }

      

       Person *pPerson = (Person*)lpParam;        //指向线程结构体的指针

    printf("   Reader %d 正在请求使用共享缓冲区...\n",pPerson->m_nID);

    WaitForSingleObject(g_hR_R_Mutex,INFINITE);      //用读者_读者互斥对象的句柄实现互斥,以修改g_NumOfReading

    if(g_NumOfReading ==0)                                        //本线程是第一个读者

    {

        WaitForSingleObject(g_hW_R_Mutex,INFINITE);     //用写者_读者互斥对象的句柄实现互斥

    }

    g_NumOfReading++;                         //读者数量+1

    ReleaseMutex(g_hR_R_Mutex);           //释放读者_读者互斥对象的句柄

    printf("   Reader %d 请求成功\n",pPerson->m_nID);

    // 修改读者的实际启动时间

    pPerson->m_nStartTime = g_CurrentTime;        //当前时间

    printf("   Reader %d 正在读共享缓冲区...\n",pPerson->m_nID);

    while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nRunTime)

    {

        // ...  执行读操作

    }

    printf("   Reader %d 正在退出...\n",pPerson->m_nID);

    WaitForSingleObject(g_hR_R_Mutex,INFINITE);      //用读者_读者互斥对象的句柄实现互斥,以修改g_NumOfReading

    g_NumOfReading--;      //读者数量-1

    if(g_NumOfReading == 0)          //本线程是最后一个读者

              ReleaseMutex(g_hW_R_Mutex);   //释放写者_读者互斥对象的句柄

    ReleaseMutex(g_hR_R_Mutex);           //释放读者_读者互斥对象的句柄

    ExitThread(0);

    return 0;

}     //DWORD  WINAPI ReaderProc(LPVOID lpParam)

DWORD  WINAPI WriterProc(LPVOID lpParam)   //指定写者线程执行的功能函数

{

       WaitForSingleObject(g_hW_W_Mutex,INFINITE);    //用写者_写者互斥对象的句柄实现互斥,以修改g_NumOfWriting

       g_NumOfWriting++;     //写者数量+1

       ReleaseMutex(g_hW_W_Mutex);         //释放写者_写者互斥对象的句柄

       WaitForSingleObject(g_hW_R_Mutex,INFINITE);     //用读者_读者互斥对象的句柄实现互斥

       Person *pPerson = (Person*)lpParam;         //指向线程结构体的指针

    // 修改写者的实际启动时间

    pPerson->m_nStartTime = g_CurrentTime;

    printf("   Writer %d 正在写共享缓冲区...\n",pPerson->m_nID);

    while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nRunTime)

    {

        // ...  执行写操作

    }

    printf("   Writer %d 正在退出...\n",pPerson->m_nID);

       WaitForSingleObject(g_hW_W_Mutex,INFINITE);    //用写者_写者互斥对象的句柄实现互斥,以修改g_NumOfWriting

       g_NumOfWriting--;       //写者数量-1

       ReleaseMutex(g_hW_W_Mutex);         //释放写者_写者互斥对象的句柄

      

       ExitThread(0);

    return 0;

}     //DWORD  WINAPI WriterProc(LPVOID lpParam)

bool CreateReader(int iStartTime,int iRunTime)  //生成读者线程

{

    DWORD dwThreadID;

    if(g_NumPerson >= MAX_PERSON)         //线程数量超过最大限度

        return false;

    Person *pPerson       = &g_Persons[g_NumPerson];     //指向线程结构体数组的指针

    pPerson->m_nID        = g_NumPerson;                      //线程ID赋值为其当前数量

    pPerson->m_nStartTime = iStartTime;

    pPerson->m_nRunTime   = iRunTime;

    pPerson->m_nType      = READER;

    g_NumPerson++;          //线程数量+1

    // 生成一个新的读者线程

    pPerson->m_hThread = CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);

    if(pPerson->m_hThread == NULL)

        return false;

     return true;

}     //bool CreateReader(int iStartTime,int iRunTime)

bool CreateWriter(int iStartTime,int iRunTime)   //生成写者线程

{

    DWORD dwThreadID;

    if(g_NumPerson >= MAX_PERSON)         //线程数量超过最大限度

        return false;

    Person *pPerson       = &g_Persons[g_NumPerson];     //指向线程结构体数组的指针

    pPerson->m_nID        = g_NumPerson;                      //线程ID赋值为其当前数量

    pPerson->m_nStartTime = iStartTime;

    pPerson->m_nRunTime   = iRunTime;

    pPerson->m_nType      = WRITER;

    g_NumPerson++;          //线程数量

    // 生成一个新的写者线程

    pPerson->m_hThread = CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID);

    if(pPerson->m_hThread == NULL)

        return false;

    return true;

}     //bool CreateWriter(int iStartTime,int iRunTime)

A.2  进程调度算法参考源程序

进程调度算法有FIFO,优先级调度算法,时间片轮转调度算法,短进程优先调度算法,多级反馈调度算法,目前主要是考虑FIFO,优先级调度算法(静态优先级),时间片轮转调度算法,短进程优先调度算法。

输入:进程流文件,其中存储的是一系列要执行的进程,

每个进程包括四个数据项:

进程名(长度不超过20个的字符串) 进程状态(1就绪 2等待 3运行) 所需时间 优先级(0级最高)

输出:

进程执行流  运行时间  等待时间 平均等待时间

本程序包括:FIFO,优先级调度算法,时间片轮转调度算法,短进程优先调度算法

VC++6.0调试通过  项目类型:Win32 Console Application

/************************************************************************************************************************************

*   Source File Name :   LGY_CPU_Scheduler                                                                                          *

*   Project Name:        LGY_CPU_Scheduler                                                                                          *

*   Engineer:            赖国勇                                                                                                     *

*   Date Generated:      20##-11-19                                                                                                 *

*   Last Revision Date:  20##-04-12                                                                                                 *

*   Brief Description:                                                                                                               *

*     [实验内容]                                                                                                                      *

*     ①、实验目的                                                                                                                    *

*            a、进程调度是处理机管理的核心内容。观察、体会操作系统的进程调度方法,                                                       *

*            并通过一个简单的进程调度模拟程序的实现,加深对进程控制块、进程队列、进程调度算法,进程切换的理解,                          *

*            并体会和了解各种调度算法的具体实施办法。                                                                                    *

*            b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。                                                               *

*     ②、实验内容                                                                                                                    *

*            a、设计进程控制块PCB表结构,模拟实现进程调度算法:FIFO,静态优先级调度,                                                    *

*            时间片轮转调度,短进程优先调度算法,多级反馈队列调度。(实现其中之一个以上)。                                              *

*            b、编写一个进程调度程序模拟程序。模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。                                    *

*            c、由用户输入(可通过文件输入)进程名、进程状态、进程运行时间和进程优先级等数据。                                           *

*     ③、实验要求                                                                                                                    *

*            a、使用模块化设计思想来设计;                                                                                               *

*            b、给出主函数和各个算法函数的流程图。                                                                                       *

*            c、学生可按照自身条件,随意选择采用的算法,(例如:采用冒泡法编写程序,实现短进程优先调度的算法)                           *

*            d、进程调度程序模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。                                                     *

*     ④、运行结果                                                                                                                    *

*            a、给出进程的调度模拟操作排序结果。                                                                                         *

*     ⑤、提示                                                                                                                        *

*            a、每个进程可有三个状态,并假设初始状态为就绪状态。                                                                         *

*            b、为了便于处理,程序中的进程运行时间以纳秒为单位计算。                                                                     *

*            c、各进程的优先级或轮转时间数以及进程需运行的纳秒数的初始值均由用户给定。                                                   *

*            d、在优先级算法中,采用静态优先级。在时间片轮转算法中,采用可变时间片,由用户给定。                                         *

*            e、对于遇到优先级一致的情况,采用FIFO策略解决。                                                                             *

*                                                                                                                                   *

*     一、在WINDOWS中双击DEBUG目录中的EXE文件直接运行,可能会没有显示结果窗口就关闭了,这不是程序错误,解决方法是:                  *

*         1、“开始->程序->附件-命令提示符”,打开DOS命令窗口。                                                                          *

*         2、改变当前目录至EXE文件所在目录;(或者将EXE文件和测试用的文本文件一并复制到当前目录)。                                   *

*         3、输入EXE文件的完整名称(含后缀名)运行即可。(为方便输入,可以重命名EXE文件。)                                           *

*    二、 本程序包括:FIFO,优先级调度算法(静态优先级),时间片轮转调度算法,短进程优先调度算法。                                   *

*          VC++6.0调试通过  项目类型:Win32 Console Application                                                                       *

*         输入:进程流文件(文本文件),其中存储的是一系列要执行的进程,每个进程包括四个数据项:                                      *

*               进程名(长度不超过20个的字符串) 进程状态(1就绪 2等待 3运行) 所需时间 优先级(0级最高)                                     *

*         输出: 进程执行流 等待时间 平均等待时间                                                                                      *

*************************************************************************************************************************************/

#include<stdio.h>

#include<string.h>

#include<iostream.h>

const int MAXPCB=100;      //定义最大进程数

//定义进程控制块PCB结构体类型

typedef struct PCB_Node{

       char sName[20];            //进程名

       int iStatus;             //进程状态(1就绪 2等待 3运行) 当前程序中暂时全部默认为就绪处理

       int iRunTime;               //进程运行时间(纳秒)

       int iPriority;          //进程优先级(0级最高)

       int iFinished;         //进程是否执行完成标志(1:已完成;0:末完成)

       int iWaitTime;              //进程等待时间(纳秒)

}PCB;

PCB pcbs[MAXPCB];          //PCB数组队列

int iPCBNum;               //实际进程数

char sFileName[20];             //进程流文件名

void InitPCB();                    //PCB初始化函数

int ReadPCBFile();        //读进程流文件数据,存入PCB数组队列pcbs,并输出

void ReSetPCB();          //重置PCB完成标志、等待时间,以供另一个调度算法使用,并输出所读入的进程数据

void FIFO();                 //先进先出调度算法

void Priority();             //优先级调度算法

void RR();                           //时间片轮转调度算法

void SPF();                         //短进程优先调度算法

void Hint();                  //显示实验提示信息函数

void Version();                     //显示版权信息函数

void InitPCB()                     //PCB初始化函数

{

       int i;

       for(i=0;i<MAXPCB;i++)

       {

              strcpy(pcbs[i].sName,"");

              pcbs[i].iStatus=-1;

              pcbs[i].iRunTime=-1;

              pcbs[i].iPriority=-1;

             

              pcbs[i].iFinished=0;

              pcbs[i].iWaitTime=0;

       } //for(i=0;i<MAXPCB;i++)

      

       iPCBNum=0;

} //void InitPCB()

int ReadPCBFile()  //读进程流文件数据,存入PCB数组队列pcbs,并输出

{

       FILE *fp;

       int i;

       char cHead;

      

       cout<<"   请输入进程流(文本)文件名(注意:包括后缀名):  ";

       cin>>sFileName;

       if((fp=fopen(sFileName,"r"))==NULL)

       {

              cout<<"   错误:进程流文件 "<<sFileName<<" 打不开,请检查文件名和路径!!"<<endl;

              return 0;

       }

       else  //if((fp=fopen(sFileName,"r"))==NULL)

       {

              cHead=fgetc(fp);

              while(cHead==' '||cHead==10||cHead==9)    //过滤空格、换行和TAB字符

              {

                     cHead=fgetc(fp);

              }

              if(cHead==EOF)

              {

                     printf("   错误:进程流文件:%s 为空!!\n",sFileName );

                     return 0;

              }

              else  //if(cHead==EOF)

              {

                     fseek( fp, -1, SEEK_CUR);

                     while(!feof(fp))

                     {

                            fscanf(fp,"%s %d %d %d",pcbs[iPCBNum].sName,&pcbs[iPCBNum].iStatus,&pcbs[iPCBNum].iRunTime,&pcbs[iPCBNum ].iPriority);

                            iPCBNum++;

                     }     //while(!feof(fp))

                    

                     //输出所读入的进程数据

                     cout<<endl<<"       从文件 "<<sFileName<<" 读入的进程数据:"<<endl<<endl;

                     cout<<"   进程名  进程状态  运行时间  优先级"<<endl;

                     for(i=0;i<iPCBNum;i++)

                     {

                            cout<<"   "<<pcbs[i].sName<<"    "<<pcbs[i].iStatus<<"   "<<pcbs[i].iRunTime<<"            "<<pcbs[i].iPriority<<endl;

                     }

                     cout<<"   进程总数:"<<iPCBNum<<endl;

                     return 1;

              }     //if(cHead==EOF)        

               

       }     //if((fp=fopen(sFileName,"r"))==NULL)    

}// int ReadPCBFile()

void ReSetPCB()    //重置PCB完成标志、等待时间,以供另一个调度算法使用,并输出所读入的进程数据

{

       int i;

      

       //输出所读入的进程数据

       cout<<endl<<"---------------------------------------------------------------"<<endl;

       cout<<endl<<"       从文件 "<<sFileName<<" 读入的进程数据:"<<endl<<endl;

       cout<<"   进程名  进程状态  运行时间  优先级"<<endl;

       for(i=0;i<iPCBNum;i++)

       {

              pcbs[i].iFinished=0;

              pcbs[i].iWaitTime=0;

              cout<<"   "<<pcbs[i].sName<<"    "<<pcbs[i].iStatus<<"   "<<pcbs[i].iRunTime<<"            "<<pcbs[i].iPriority<<endl;

       }

       cout<<"   进程总数:"<<iPCBNum<<endl;

} //void ReSetPCB()

void FIFO() //先进先出调度算法

{

       int i,j;

       int iSum; //总等待时间

       //输出先进先出调度算法执行流

       cout<<endl<<"---------------------------------------------------------------"<<endl;

       cout<<"   先进先出调度算法执行流:"<<endl<<endl;

       cout<<"   序号 进程名 运行时间 等待时间"<<endl;

       iSum=0;

       for(i=0;i<iPCBNum;i++)

       {

              cout<<"   "<<i+1<<"    "<<pcbs[i].sName<<"  "<<pcbs[i].iRunTime<<"     "<<pcbs[i].iWaitTime<<endl;

              iSum+=pcbs[i].iWaitTime;    //累加总等待时间

             

              for(j=i+1;j<iPCBNum;j++)

              {

                     pcbs[j].iWaitTime+=pcbs[i].iRunTime;

              }

       }

       cout<<"   总调度次数:"<<iPCBNum<<endl;

       cout<<"   总等待时间:"<<iSum<<endl;

       printf("   平均等待时间  %.2f\n",(float)iSum / (float)iPCBNum);

       cout<<endl<<"---------------------------------------------------------------"<<endl;

} //void FIFO()

void Priority() //优先级调度算法

{

       int i,j;

       int iCurMin;          //当前最低优先级PCB在数组pcbs中的下标

       int iPassedTime=0; //已经过的时间

       int iSum;               //总等待时间

       int iQueue[MAXPCB];         //用于存放排序后进程数组下标的数组队列

       int iCurPriority=1000;   //当前最低优先级

       for(i=0;i<iPCBNum;i++)  //按优先级递增排序PCB,将排序后下标的存放在iQueue队列中。  (选择排序)

       {

              iCurPriority=1000;

              for(j=0;j<iPCBNum;j++)

              {

                     if((pcbs[j].iFinished==0)&&(pcbs[j].iPriority<iCurPriority))

                     {

                            iCurMin=j;

                            iCurPriority=pcbs[j].iPriority;

                     }

              } //for(j=0;j<iPCBNum;j++)

              iQueue[i]=iCurMin;

              pcbs[iCurMin].iFinished=1;

              pcbs[iCurMin].iWaitTime+=iPassedTime;

              iPassedTime+=pcbs[iCurMin].iRunTime;

       }     //for(i=0;i<iPCBNum;i++)

      

       //输出优先级调度执行流

       cout<<endl<<"---------------------------------------------------------------"<<endl;

       cout<<"   优先级调度执行流:"<<endl<<endl;

       cout<<"   序号 进程名 优先级 运行时间 等待时间"<<endl;

       iSum=0;

       for(i=0;i<iPCBNum;i++)

       {

              cout<<"   "<<i+1<<"    "<<pcbs[iQueue[i]].sName<<"     "<<pcbs[iQueue[i]].iPriority<<"       "<<pcbs[iQueue[i]].iRunTime<<" "<<pcbs[iQueue[i]].iWaitTime<<endl;

              iSum+=pcbs[iQueue[i]].iWaitTime;      //累加总等待时间

       }

       cout<<"   总调度次数:"<<iPCBNum<<endl;

       cout<<"   总等待时间:"<<iSum<<endl;

       printf("   平均等待时间  %.2f\n",(float)iSum / (float)iPCBNum);

       cout<<endl<<"---------------------------------------------------------------"<<endl;

      

} //void Priority()

void RR()       //时间片轮转调度算法

{

       int i;

       int iNotEnded=1;          //标志:不是所有进程都已经获得足够时间片运行完成

       int iNum;                     //到目前为止末执行完的进程数

       int iRound=0;               //轮转周期数

       int iSum=0;                         //总时间片数

       float fBlockTime=10;    //时间片的长度(纳秒)

      

       cout<<endl<<"       请输入时间片的长度(纳秒):"<<endl<<"      ";

       cin>>fBlockTime;

       cout<<endl<<"---------------------------------------------------------------"<<endl;

       cout<<"   时间片轮转调度执行流(时间片的长度为:"<<fBlockTime<<"纳秒):"<<endl;

       while(iNotEnded==1)

       {

              iNotEnded=0;

              iNum=0;

             

              for(i=0;i<iPCBNum;i++)      //统计到目前为止末执行完的进程数iNum

              {

                     if(pcbs[i].iFinished==0)

                     {

                            iNum++;

                           

                     } //if(pcbs[i].iFinished==0)

              } //for(i=0;i<iPCBNum;i++)

             

              if(iNum>0)

              {

                     iRound++;      //累加轮转周期数

                     cout<<endl<<"       第"<<iRound<<"轮:";

                     for(i=0;i<iPCBNum;i++)

                     {

                            if(pcbs[i].iFinished==0)

                            {

                                   iNotEnded=1;

                                  

                                   cout<<pcbs[i].sName<<" ";

                                   iSum++;  //累加总时间片数

                                   if(pcbs[i].iRunTime<=fBlockTime*(iRound))

                                   //i进程在本轮获得一个时间片后能够运行完成

                                   {

                                          pcbs[i].iFinished=1;

                                   } //if(pcbs[i].iRunTime<=fBlockTime*(iRound+1))

                            }//if(pcbs[i].iFinished==0)

                     } //for(i=0;i<iPCBNum;i++)       

              } //if(iNum>0)

       } //while(iNotEnded==1)

      

       cout<<endl<<"       轮转周期数:"<<iRound<<"  总时间片数:"<<iSum<<endl;

       cout<<endl<<"---------------------------------------------------------------"<<endl;

}//void RR()

void SPF()     //短进程优先调度算法

{

       int i,j;

       int iCurMin;          //当前最短运行时间PCB在数组pcbs中的下标

       int iPassedTime=0; //已经过的时间

       int iSum;               //总等待时间

       int iQueue[MAXPCB]; //用于存放排序后进程数组下标的数组队列

       int iCurRunTime;   //当前最短进程运行时间

       for(i=0;i<iPCBNum;i++)  //按进程运行时间递增排序PCB,将排序后下标的存放在iQueue队列中。  (选择排序)

       {

              iCurRunTime=1000000;

              for(j=0;j<iPCBNum;j++)

              {

                     if((pcbs[j].iFinished==0)&&(pcbs[j].iRunTime<iCurRunTime))

                     {

                            iCurMin=j;

                            iCurRunTime=pcbs[j].iRunTime;

                     }

              } //for(j=0;j<iPCBNum;j++)

              iQueue[i]=iCurMin;

              pcbs[iCurMin].iFinished=1;

              pcbs[iCurMin].iWaitTime+=iPassedTime;

              iPassedTime+=pcbs[iCurMin].iRunTime;

       }     //for(i=0;i<iPCBNum;i++)

      

       //输出短进程优先调度执行流

       cout<<endl<<"---------------------------------------------------------------"<<endl;

       cout<<"   短进程优先调度执行流:"<<endl<<endl;

       cout<<"   序号 进程名 运行时间 等待时间"<<endl;

       iSum=0;

       for(i=0;i<iPCBNum;i++)

       {

              cout<<"   "<<i+1<<"    "<<pcbs[iQueue[i]].sName<<"    "<<pcbs[iQueue[i]].iRunTime<<"      "<<pcbs[iQueue[i]].iWaitTime<<endl;

              iSum+=pcbs[iQueue[i]].iWaitTime;      //累加总等待时间

       }

       cout<<"   总调度次数:"<<iPCBNum<<endl;

       cout<<"   总等待时间:"<<iSum<<endl;

       printf("   平均等待时间  %.2f\n",(float)iSum / (float)iPCBNum);

       cout<<endl<<"---------------------------------------------------------------"<<endl;

      

} //void SPF ()

void Hint() //显示实验提示信息函数

{

       cout<<endl;

      

       cout<<"  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                 "<<endl;

       cout<<"  [实验内容]                                                                      "<<endl;

       cout<<"  ①、实验目的                                                                    "<<endl;

       cout<<"  a、进程调度是处理机管理的核心内容。观察、体会操作系统的进程调度方法,           "<<endl;

       cout<<"  并通过一个简单的进程调度模拟程序的实现,加深对进程控制块、进程队列、            "<<endl;

       cout<<"  进程调度算法,进程切换的理解,并体会和了解各种调度算法的具体实施办法。          "<<endl;

       cout<<"  b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。                   "<<endl;

       cout<<"  ②、实验内容                                                                    "<<endl;

       cout<<"  a、设计进程控制块PCB表结构,模拟实现进程调度算法:FIFO,静态优先级调度,        "<<endl;

       cout<<"  时间片轮转调度,短进程优先调度算法,多级反馈队列调度(实现其中之一个以上)。    "<<endl;

       cout<<"  b、编写一个进程调度程序模拟程序。模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。    "<<endl;

       cout<<"  c、由用户输入(可通过文件输入)进程名、进程状态、进程运行时间和进程优先级等数据。 "<<endl;

       cout<<"  ③、实验要求                                                                       "<<endl;

       cout<<"  a、使用模块化设计思想来设计;                                                        "<<endl;

       cout<<"  b、给出主函数和各个算法函数的流程图。                                                            "<<endl;

       cout<<"  c、学生可按照自身条件,随意选择采用的算法,(例如:采用冒泡法编写程序,实现短进程优先调度的算法)。 "<<endl;

       cout<<"  d、进程调度程序模拟程序只对PCB进行相应的调度模拟操作,不需要实际程序。                                 "<<endl;

       cout<<"  ④、运行结果                                                                                     "<<endl;

       cout<<"  a、给出进程的调度模拟操作排序结果。                                                              "<<endl;

       cout<<"  ⑤、提示                                                                                         "<<endl;

       cout<<"  a、每个进程可有三个状态,并假设初始状态为就绪状态。                                              "<<endl;

       cout<<"  b、为了便于处理,程序中的进程运行时间以纳秒为单位计算。                                          "<<endl;

       cout<<"  c、各进程的优先级或轮转时间数以及进程需运行的纳秒数的初始值均由用户给定。                        "<<endl;

       cout<<"  d、在优先级算法中,采用静态优先级。在时间片轮转算法中,采用可变时间片,由用户给定。              "<<endl;

       cout<<"  e、对于遇到优先级一致的情况,采用FIFO策略解决。                                                  "<<endl;

       cout<<"  一、在WINDOWS中双击DEBUG目录中的EXE文件直接运行,可能会没有显示结果窗口就关闭了,这不是程序错误,解决方法是:"<<endl;

       cout<<"  1、“开始->程序->附件-命令提示符”,打开DOS命令窗口。                                             "<<endl;

       cout<<"  2、改变当前目录至EXE文件所在目录;(或者将EXE文件和测试用的文本文件一并复制到当前目录)。        "<<endl;

       cout<<"  3、输入EXE文件的完整名称(含后缀名)运行即可。(为方便输入,可以重命名EXE文件。)                "<<endl;

       cout<<"  二、本程序包括:FIFO,优先级调度算法(静态优先级),时间片轮转调度算法,短进程优先调度算法。 VC++6.0调试通过  项目类型:Win32 Console Application。"<<endl;

       cout<<"  输入:进程流文件(文本文件),其中存储的是一系列要执行的进程,每个进程包括四个数据项:           "<<endl;

       cout<<"       进程名(长度不超过20个的字符串) 进程状态(1就绪 2等待 3运行) 所需时间 优先级(0级最高)                                   "<<endl;

       cout<<"  输出: 进程执行流 等待时间 平均等待时间                                                           "<<endl;

       cout<<"  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                 "<<endl;

       cout<<endl;

} //void Hint()

void Version() //显示版权信息函数

{

       cout<<endl<<endl;

      

       cout<<"   ┏━━━━━━━━━━━━━━━━━━━━━━━┓"<<endl;

       cout<<"   ┃     进程调度算法模拟系统         ┃"<<endl;

       cout<<"   ┠───────────────────────┨"<<endl;

       cout<<"   ┃       (c)All Right Reserved          ┃"<<endl;

       cout<<"   ┃         LGY  赖国勇            ┃"<<endl;

       cout<<"   ┃     Version 20## build 2.1        ┃"<<endl;

       cout<<"   ┗━━━━━━━━━━━━━━━━━━━━━━━┛"<<endl;

       cout<<endl<<endl;

} //void Version()

void main()           //主函数

{

       int iInput;              //用户输入的整数以选择算法

       bool bGoOn;          //是否继续进程调度算法模拟的标志

       char sGoOn[1];      //用户输入是否继续进程调度算法模拟的字母:y、Y、N、n

       Hint();                  //显示实验提示信息函数

       Version();              //显示版权信息函数

      

       InitPCB();             //PCB初始化函数

      

       bGoOn= true;

       strcpy(sGoOn," ");

             

       if(ReadPCBFile()==1)   //标志 读进程流文件数据函数 执行是否正确

       {

              while (bGoOn)

              {

                     cout<<endl<<"       请输入算法编号(1 OR 2 OR 3 OR 4)选择进程调度算法:"<<endl<<endl;      

                     cout<<"   1  先进先出调度算法"<<endl<<endl<<"   2  优先级调度算法"<<endl<<endl;

                     cout<<"   3  时间片轮转调度算法"<<endl<<endl<<"      4  短进程优先调度算法"<<endl<<endl<<" ";

                     cin>>iInput;          //从标准输入获取用户输入的整数以选择算法

                     switch(iInput)

                     {

                     case 1:

                            ReSetPCB();          //重置PCB完成标志、等待时间,以供另一个调度算法使用,并输出所读入的进程数据

                            FIFO();                 //先进先出调度算法

                            break;

                           

                     case 2:

                            ReSetPCB();          //重置PCB完成标志、等待时间,以供另一个调度算法使用,并输出所读入的进程数据

                            Priority();              //优先级调度算法

                            break;

                           

                     case 3:

                            ReSetPCB();          //重置PCB完成标志、等待时间,以供另一个调度算法使用,并输出所读入的进程数据

                            RR();                    //时间片轮转调度算法

                            break;

                           

                     case 4:

                            ReSetPCB();          //重置PCB完成标志、等待时间,以供另一个调度算法使用,并输出所读入的进程数据

                            SPF();                   //短进程优先调度算法

                            break;

                     default:

                            printf("\n 输入的算法编号错误!!\n"); 

                            return;

                           

                     }     //switch(iInput)

                    

                     bGoOn= false;

                     strcpy(sGoOn," ");

                    

                     cout<<endl<<"       要继续进行进程调度算法模拟吗?(Y/N)"<<endl<<" ";

                     cin>>sGoOn;        

                     bGoOn=(sGoOn[0]=='y'||sGoOn[0]=='Y');

                                         

              }//while bGoOn

       } //if(ReadPCBFile()==1)

}//void main()

A.3  磁盘调度算法参考源程序

/***********************************************************************************************************

*   Source File Name :   LGY_DISK_Scheduler.cpp                                                            *

*   Project Name:        LGY_DISK_Scheduler                                                                *

*   Engineer:            赖国勇                                                                            *

*   Date Generated:      20##-11-29                                                                        *

*   Last Revision Date:  20##-04-11                                                                        *

*   Brief Description:                                                                                      *

*   ①、实验目的                                                                                           *

*          a、观察、体会操作系统的磁盘调度方法,并通过一个简单的磁盘调度模拟程序的实现,加深对磁盘调度的理解。*

*          b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。                                      *

*   ②、实验内容                                                                                           *

*            a、模拟实现磁盘调度算法:FCFS,最短寻道优先,电梯算法(实现其中之一种以上)。                      *

*         b、磁道请求服务顺序由用户输入(可通过从指定的文本文件(TXT文件)中取出)。                         *

*     ③、实验要求                                                                                           *

*         a、使用模块化设计思想来设计。                                                                      *

*          b、给出主函数和各个算法函数的流程图。                                                              *

*          c、学生可按照自身条件,随意选择采用的算法。                                                        *

*     ④、运行结果                                                                                           *

*        a、给出磁盘调度算法模拟程序对进程寻道请求的排序结果。                                               *

*     输出:                                                                                                 *

*          第一列:序号;                                                                                     *

*          第二列:磁道的服务顺序;                                                                           *

*         第三列:移动的磁道数;                                                                             *

*         最后计算出总移动磁道数、平均移动磁道数。                                                           *

*                                                                                                            *

*     本程序包括:先来先服务算法,最短寻道优先调度算法,电梯算法                                              *

*     VC++6.0调试通过     项目类型:Win32 Console Application                                                *

*                                                                                                          *

************************************************************************************************************/

#include<stdio.h>

#include<iostream.h>

#include<string.h>

#include<math.h>

const int MAXQUEUE=200; //定义请求队列最大长度

//磁道号请求结构体定义

typedef struct TRACK_Node

{

       int iGo;          //要访问的磁道号

       int iVisited;     //磁道是否已经访问标志(1:已访问;0:末访问)

}TRACK;

TRACK queue[MAXQUEUE]; //磁道号请求队列数组

int iReqNum=0;                   //磁道访问请求数

int iStart=0;                  //磁头初始位置

int iNow=0;                         //磁头当前位置

int iSum=0;                         //总移动磁道数

int iInput;                            //用户当前输入的整数

char sFileName[20];             //文件名

void Init();                   //初始化函数

void Reset();                 //重置访问标志、磁头当前位置、总移动磁道数

int ReadTrackFile();      //读入磁道号流文件

void FCFS();                //先来先服务调度算法

void SSTF();                //最短寻道优先调度算法

void SCAN();               //电梯调度算法

void Version();                     //显示版权信息函数

void Hint();                  //显示实验提示信息函数

void Init()      //初始化函数

{

       int i;

      

       for(i=0;i<MAXQUEUE;i++)

       {

              queue[i].iGo=-1;           //设置要访问的磁道号为不可能的数-1,以区别正常请求磁道号

              queue[i].iVisited=0;       //设置磁道是否已经访问标志为0:末访问

       }

      

} //void Init()

void Reset()    //重置访问标志、磁头当前位置、总移动磁道数

{

       int i;

      

       for(i=0;i<iReqNum;i++)

       {

              queue[i].iVisited=0;      //设置磁道是否已经访问标志为0:末访问

       }

       printf( "\n       请输入磁头的初始磁道号(整数):  ");

       scanf("%d",&iStart);     //从标准输入获取用户当前输入的磁头初始位置

       iNow=iStart;                 //磁头当前位置

       iSum=0;                              //总移动磁道数

      

} //void Reset()

int ReadTrackFile() //读入磁道号流文件

{

       FILE *fp;     

       int iTemp;

       char cHead;

      

       cout<<"   \n    请输入磁道号流(文本)文件名(注意:包括后缀名):  ";

       cin>>sFileName;          //从标准输入获取用户当前输入的文件名

      

       if((fp=fopen(sFileName,"r"))==NULL)

       {

              cout<<endl<<"       错误:磁道号流文件 "<<sFileName<<" 打不开,请检查文件名和路径!!"<<endl;

              return -1;

             

       }

       else

       {

              cHead=fgetc(fp);

              while(cHead==' '||cHead==10||cHead==9)    //过滤空格、换行和TAB字符

              {

                     cHead=fgetc(fp);

              }

              if(cHead==EOF)

              {

                     printf("   错误:磁道号流文件:%s 为空!!\n",sFileName );

                     return -1;

              }

              else

              {

                     fseek( fp, -1, SEEK_CUR);

                     while(!feof(fp))     //将文件中输入的磁道号依次存入磁道号请求队列数组

                     {

                            fscanf(fp,"%d ",&iTemp);

                            queue[iReqNum].iGo=iTemp;

                            iReqNum++;   //磁道访问请求数

                     }

              }

       }     //if((fp=fopen(sFileName,"r"))==NULL)

       return 0;

} //void ReadTrackFile()

void FCFS() //先来先服务调度算法

{

       int i;

      

       Reset();   //重置访问标志、磁头当前位置、总移动磁道数

      

       cout<<endl<<"---------------------------------------------"<<endl;

       cout<<"   先来先服务调度算法的调度结果:  "<<endl<<endl;

       cout<<"       初始磁道号:  "<<iStart<<endl;

       cout<<"   序号  下一磁道号  移动的磁道数"<<endl;

      

       for(i=0;i<iReqNum;i++)

       {

              cout<<"            "<<i+1<<"      "<<queue[i].iGo<<"      "<<abs(queue[i].iGo-iNow)<<endl;

              iSum+=abs(queue[i].iGo-iNow);          //累加总移动磁道数

              iNow=queue[i].iGo;                                  //设置磁头当前位置为当前访问磁道号

       }

       cout<<endl<<"       总调度次数:  "<<iReqNum<<endl;

       cout<<endl<<"       总移动磁道数:  "<<iSum<<endl;

       printf("\n 平均移动磁道数:  %.2f\n\n",(float)iSum / (float)iReqNum);

} //void FCFS()

void SSTF() //最短寻道优先调度算法

{

       int i,j;

       int iNext; //下一磁道号

       Reset();   //重置访问标志、磁头当前位置、总移动磁道数     cout<<endl<<"---------------------------------------------"<<endl;

       cout<<endl<<"---------------------------------------------"<<endl;

       cout<<"   最短寻道优先调度算法的调度结果:  "<<endl<<endl;

       cout<<"       初始磁道号:  "<<iStart<<endl;

       cout<<"   序号  下一磁道号  移动的磁道数"<<endl;

      

       for(i=0;i<iReqNum;i++)

       {

              iNext=0;

              while(queue[iNext].iVisited!=0)    //跳过已访问的磁道号

              {

                     iNext++;

              } //while

             

              for(j=iNext;j<iReqNum;j++)

              {

                     //寻找下一个寻道距离最短的末访问磁道号

                     if((queue[j].iVisited==0)&&(abs(iNow-queue[iNext].iGo)>abs(iNow-queue[j].iGo)))

                     {

                            iNext=j;

                     }

              } //for(j=iNext;j<iReqNum;j++)

              cout<<"            "<<i+1<<"      "<<queue[iNext].iGo<<"      "<<abs(queue[iNext].iGo-iNow)<<endl;

              iSum+=abs(queue[iNext].iGo-iNow);        //累加总移动磁道数

              queue[iNext].iVisited=1;                            //设置磁道是否已经访问标志为1:已访问

              iNow=queue[iNext].iGo;                                 //设置磁头当前位置为当前访问磁道号

       } //for(i=0;i<iReqNum;i++)

       cout<<endl<<"       总调度次数:  "<<iReqNum<<endl;

       cout<<endl<<"       总移动磁道数:  "<<iSum<<endl;

       printf("\n 平均移动磁道数:  %.2f\n\n",(float)iSum / (float)iReqNum);

} //void SSTF()

void SCAN()  //电梯调度算法

{

       int i,j;

       int iNext;        //下一磁道号

       int iMinMove; //当前方向上最短寻道距离

       cout<<endl<<"---------------------------------------------"<<endl;

      

       cout<<endl<<"       请选择磁头初始方向(1 OR 2):"<<endl<<endl;

       cout<<"   1  磁头初始向内"<<endl<<endl<<"   2  磁头初始向外"<<endl<<endl<<"   ";

       cin>>iInput;   //从标准输入获取用户当前输入的整数

      

       switch(iInput) //用户当前输入的整数

       {

       case 1:                   //磁头初始向内

              Reset();   //重置访问标志、磁头当前位置、总移动磁道数

             

              cout<<endl<<"---------------------------------------------"<<endl;

              cout<<"   电梯调度算法——磁头初始向内的调度结果:  "<<endl<<endl;

              cout<<"       初始磁道号:  "<<iStart<<endl;

              cout<<"   序号  下一磁道号  移动的磁道数"<<endl;

              for(i=0;i<iReqNum;i++)

              {

                     iMinMove=9999;

                     iNext=-1;

                     for(j=0;j<iReqNum;j++)       //寻找当前方向上寻道距离最短的末访问磁道号

                     {

                            if((queue[j].iVisited==0)&&(queue[j].iGo>=iNow))

                            {

                                   if(abs(queue[j].iGo-iNow)<iMinMove)

                                   {

                                          iNext=j;

                                          iMinMove=abs(queue[j].iGo-iNow);

                                   } //if(abs(queue[j].iGo-iNow)<iMinMove)

                            } //if((queue[j].iVisited==0)&&(queue[j].iGo>=iNow))

                     } //for(j=0;j<iReqNum;j++)

                     if(iNext!=-1)

                     {

                            cout<<"            "<<i+1<<"      "<<queue[iNext].iGo<<"      "<<abs(queue[iNext].iGo-iNow)<<endl;

                            iSum+=abs(queue[iNext].iGo-iNow);        //累加总移动磁道数

                            iNow=queue[iNext].iGo;                                   //设置磁头当前位置为当前访问磁道号

                            queue[iNext].iVisited=1;                            //设置磁道是否已经访问标志为1:已访问

                     } //if(iNext!=-1)

                     else  //掉头向外

                     {

                            for(j=0;j<iReqNum;j++)              //寻找当前方向上寻道距离最短的末访问磁道号

                            {

                                   if((queue[j].iVisited==0)&&(queue[j].iGo<iNow))

                                   {

                                          if(abs(queue[j].iGo-iNow)<iMinMove)

                                          {

                                                 iNext=j;

                                                 iMinMove=abs(queue[j].iGo-iNow);

                                          }

                                   }

                            } //for(j=0;j<iReqNum;j++)

                            cout<<"            "<<i+1<<"      "<<queue[iNext].iGo<<"      "<<abs(queue[iNext].iGo-iNow)<<endl;

                            iSum+=abs(queue[iNext].iGo-iNow);        //累加总移动磁道数

                            iNow=queue[iNext].iGo;                                 //设置磁头当前位置为当前访问磁道号

                            queue[iNext].iVisited=1;                            //设置磁道是否已经访问标志为1:已访问

                     } //if(iNext!=-1)

              } //for(i=0;i<iReqNum;i++)

              cout<<endl<<"       总调度次数:  "<<iReqNum<<endl;

              cout<<endl<<"       总移动磁道数:  "<<iSum<<endl;

              printf("\n 平均移动磁道数:  %.2f\n\n",(float)iSum / (float)iReqNum);

              break;

       case 2:                   //磁头初始向外

           Reset();   //重置访问标志、磁头当前位置、总移动磁道数

      

              cout<<endl<<"---------------------------------------------"<<endl;

              cout<<endl<<endl<<"    电梯调度算法——磁头初始向外的调度结果:  "<<endl<<endl;

              cout<<"       初始磁道号:  "<<iStart<<endl;

              cout<<"   序号  下一磁道号  移动的磁道数"<<endl;

              for(i=0;i<iReqNum;i++)

              {

                     iMinMove=9999;

                     iNext=-1;

                     for(j=0;j<iReqNum;j++)              //寻找当前方向上寻道距离最短的末访问磁道号

                     {

                            if((queue[j].iVisited==0)&&(queue[j].iGo<=iNow))

                            {

                                   if(abs(queue[j].iGo-iNow)<iMinMove)

                                   {

                                          iNext=j;

                                          iMinMove=abs(queue[j].iGo-iNow);

                                   } //if(abs(queue[j].iGo-iNow)<iMinMove)

                            } //if((queue[j].iVisited==0)&&(queue[j].iGo<=iNow))

                     } //for(j=0;j<iReqNum;j++)

             

                     if(iNext!=-1)

                     {

                            cout<<"            "<<i+1<<"      "<<queue[iNext].iGo<<"      "<<abs(queue[iNext].iGo-iNow)<<endl;

                            iSum+=abs(queue[iNext].iGo-iNow);          //累加总移动磁道数

                            iNow=queue[iNext].iGo;                                 //设置磁头当前位置为当前访问磁道号

                            queue[iNext].iVisited=1;                            //设置磁道是否已经访问标志为1:已访问

                     }

                     else  //掉头向内

                     {

                            for(j=0;j<iReqNum;j++)              //寻找当前方向上寻道距离最短的末访问磁道号

                            {

                                   if((queue[j].iVisited==0)&&(queue[j].iGo>iNow))

                                   {

                                          if(abs(queue[j].iGo-iNow)<iMinMove)

                                          {

                                                 iNext=j;

                                                 iMinMove=abs(queue[j].iGo-iNow);

                                          }     //if(abs(queue[j].iGo-iNow)<iMinMove)

                                   }     //if((queue[j].iVisited==0)&&(queue[j].iGo>iNow))

                            }     //for(j=0;j<iReqNum;j++)

      

                            cout<<"            "<<i+1<<"      "<<queue[iNext].iGo<<"      "<<abs(queue[iNext].iGo-iNow)<<endl;

                            iSum+=abs(queue[iNext].iGo-iNow);        //累加总移动磁道数

                            iNow=queue[iNext].iGo;                                 //设置磁头当前位置为当前访问磁道号

                            queue[iNext].iVisited=1;                            //设置磁道是否已经访问标志为1:已访问

                     }     //if(iNext!=-1)

              }     //for(i=0;i<iReqNum;i++)

              cout<<endl<<"       总调度次数:  "<<iReqNum<<endl;

              cout<<endl<<"       总移动磁道数:  "<<iSum<<endl;

              printf("\n 平均移动磁道数:  %.2f\n\n",(float)iSum / (float)iReqNum);

             

              break;

                                  

       default:

              printf("\n 输入错误!!\n\n");

              return;

       }     //switch(iInput)

} //void SCAN()

void Version() //显示版权信息函数

{

       cout<<endl<<endl;

      

       cout<<"         ┏━━━━━━━━━━━━━━━━━━━━━━━┓"<<endl;

       cout<<"         ┃      磁盘调度算法模拟系统            ┃"<<endl;

       cout<<"         ┠───────────────────────┨"<<endl;

       cout<<"         ┃     (c)All Right Reserved            ┃"<<endl;

       cout<<"         ┃        LGY  赖国勇             ┃"<<endl;

       cout<<"         ┃     Version 20## build 2.1        ┃"<<endl;

       cout<<"         ┗━━━━━━━━━━━━━━━━━━━━━━━┛"<<endl;

      

       cout<<endl<<endl;

}// void Version()

void Hint() //显示实验提示信息函数

{

       cout<<endl;

      

       cout<<"   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                  "<<endl;

       cout<<"     ①、实验目的                                                                                                     "<<endl;

       cout<<"     a、观察、体会操作系统的磁盘调度方法,                                   "<<endl;

       cout<<"     并通过一个简单的磁盘调度模拟程序的实现,加深对磁盘调度的理解。          "<<endl;

       cout<<"     b、提高实际动手编程能力,为日后从事软件开发工作打下坚实基础。                  "<<endl;

       cout<<"     ②、实验内容                                                                  "<<endl;

      cout<<"     a、模拟实现磁盘调度算法:FCFS,最短寻道优先,                               "<<endl;

       cout<<"     电梯算法(实现其中之一种以上)。                                            "<<endl;

       cout<<"     b、磁道请求服务顺序由用户输入(可通过从指定的文本(TXT)文件中取出)。      "<<endl;

       cout<<"     ③、实验要求                                                                                              "<<endl;

       cout<<"     a、使用模块化设计思想来设计。                                                                                   "<<endl;

       cout<<"     b、给出主函数和各个算法函数的流程图。                                             "<<endl;

       cout<<"     c、学生可按照自身条件,随意选择采用的算法。                                                        "<<endl;

       cout<<"     ④、运行结果                                                             "<<endl;

       cout<<"     a、给出磁盘调度算法模拟程序对进程寻道请求的排序结果。                                      "<<endl;

       cout<<"     输出:                                                                                                                "<<endl;

       cout<<"     第一列:序号;                                                                                              "<<endl;

       cout<<"     第二列:磁道的服务顺序;                                                                                           "<<endl;

       cout<<"     第三列:移动的磁道数;                                                                                            "<<endl;

       cout<<"     最后计算出总移动磁道数、平均移动磁道数。                                                        "<<endl;

       cout<<"                                                                                                                           "<<endl;

       cout<<"     本程序包括:先来先服务算法,最短寻道优先调度算法,电梯算法                                   "<<endl;

       cout<<"     VC++6.0调试通过   项目类型:Win32 Console Application                        "<<endl;

       cout<<"   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                  "<<endl;

       cout<<endl;

} //void Hint()

void main()

{

       int i;

       bool bGoOn;          //是否继续磁盘调度算法模拟的标志

       char sGoOn[1];      //用户输入是否继续磁盘调度算法模拟的字母:y、Y、N、n

       Hint();                  //显示实验提示信息函数

       Version();              //显示版权信息函数

      

       Init();                    //初始化函数

      

       if(ReadTrackFile()==-1)    //读入磁道号流文件

              {

                     printf("   读入磁道号流文件失败!!\n\n");

              }

              else

              {

                     bGoOn= true;

                     while (bGoOn)

                     {

                            cout<<endl<<"---------------------------------------------"<<endl;

                            cout<<"   从磁道号流文件 "<<sFileName<<" 所读入的磁道号流如下:"<<endl<<endl<<"  ";

                            for(i=0;i<iReqNum;i++)

                            {

                                   cout<<queue[i].iGo<<" ";

                            }

                            cout<<endl<<endl<<"    请求数为:  "<<iReqNum<<endl<<endl;

                            iInput=-1;              //用户输入的整数以选择算法

                            cout<<endl<<"       请输入算法编号(1 OR 2 OR 3)选择调度算法:"<<endl<<endl;

                            cout<<"   1  先来先服务调度算法"<<endl<<endl<<"      2  最短寻道优先调度算法"<<endl<<endl<<" 3  电梯调度算法  "<<endl<<endl<<" ";

                            cin>>iInput;          //从标准输入获取用户当前输入的整数

                            switch(iInput)        //用户输入的整数以选择算法

                            {

                            case 1:

                                   FCFS();         //先来先服务调度算法

                                   break;

                            case 2:

                                   SSTF();          //最短寻道优先调度算法

                                   break;

                                  

                            case 3:

                                   SCAN();        //电梯调度算法

                                   break;

                                  

                            default:

                                   printf("\n 输入的算法编号错误!!\n\n");

                                   return;

                            }     //switch(iInput)

                           

                            bGoOn= false;

                            strcpy(sGoOn," ");

                           

                            cout<<"   要继续进行磁盘调度算法模拟吗?(Y/N)    "<<endl<<"    ";

                            cin>>sGoOn;        

                            bGoOn=(sGoOn[0]=='y'||sGoOn[0]=='Y');

                     }  //while bGoOn

              }     //if(ReadTrackFile()==-1)    

             

} //void main()


附录B软件开发文档指南

1 可行性研究报告

可行性研究报告的编写目的是:说明该软件开发项目的实现在技术、经济和社会条件方面的可行性;评述为了合理地达到开发目标而可能先择的各种方案;说明论证所选定的方案。

可行性研究报告的编写内容要求如下:

  1.1 引言

  1.1.1 编写目的

  1.1.2 背景

  1.1.3 定义

  1.1.4 参考资料

  1.2 可行性研究的前提

  1.2.1 要求

  1.2.2 目标

  1.2.3 条件、假定和限制

  1.2.4 进行可行性研究的方法

  1.2.5 评价尺度

  1.3 对现有系统的分析

  1.3.1 数据流程和处理流程

  1.3.2 工作负荷

  1.3.3 费用开支

  1.3.4 人员

  1.3.5 设备

  1.3.6 局限性

  1.4 所建议的系统

  1.4.1 对所建议系统的说明

  1.4.2 数据流程各处理流程

  1.4.3 改进之处

  1.4.4 影响

  1.4.4.1 对象设备的影响

  1.4.4.2 对软件的影响

  1.4.4.3 对用户单位机构的影响

  1.4.4.4 对系统动行的影响

  1.4.4.5 对开发的影响

  1.4.4.6 对地点和设施的影响

  1.4.4.7 对经费开支的影响

  1.4.5 局限性

  1.4.6 技术条件方面的可行性

  1.5 可选择其他系统方案

  1.5.1 可选择的系统方案1

  1.5.2 可选择的系统方案2

  ……

  1.6 投资及收益分析

  1.6.1 支出

  1.6.1.1 基本建设投资

  1.6.1.2 其他一次性支出

  1.6.1.3 非一次性支出

  1.6.2 收益

  1.6.2.1 一次性收益

  1.6.2.2 非一次性收益

  1.6.2.3 不可定量的收益

  1.6.3 收益/投资比

  1.6.4 投资回收周期

  1.6.5 敏感性分析

  1.7 社会条件方面的可行性

  1.7.1 法律方面的可行性

  1.7.2 使用方面的可行性

  1.8 结论

2 项目开发计划

编制项目开发计划的目的是用文件的形式,把对于在开发过程中各项工作的负责人员、开发进度所需经费预算、所需软、硬件条件等问题作出安排记载下来,以便根据本计划开展和检查本项目的开发工作。编制内容要求如下:

  2.1 引言

  2.1.1 编写目的

  2.1.2 背景

  2.1.3 定义

  2.1.4 参考资料

  2.2 项目概述

  2.2.1 工作内容

  2.2.2 主要参加人员

  2.2.3 产品及成果

  2.2.3.1 程序

  2.2.3.2 文件

  2.2.3.3 服务

  2.2.3.4 非移交产品

  2.2.4 验收标准

  2.2.5 完成项目的最迟期限

  2.2.6 本计划的审查者与批准者

  2.3 实施总计划

  2.3.1 工作任务的分解

  2.3.2 接口人员

  2.3.3 进度

  2.3.4 预算

  2.3.5 关键问题

  2.4 支持条件

  2.4.1 计算机系统支持

  2.4.2 需要用户承担的工作

  2.4.3 需由外单位提供的条件

  2.5 专题计划要点

3 软件需求说明书

软件需求说明书的编制是为了使用户的软件开发者双方对该软件的起初规定有一个共同的理解,使之成为整个开发工作的基础。编制软件需求说明书的内容要求如下:

  3.1 引言

  3.1.1 编写的目的

  3.1.2 背景

  3.1.3 定义

  3.1.1 参考资料

  3.2 任务概述

  3.2.1 目标

  3.2.2 用户的点

  3.2.3 假定与约束

  3.3 需求规定

  3.3.1 对功能的规定

  3.3.2 对性能的规定

  3.3.2.1 精度

  3.3.2.2 时间特性要求

  3.3.2.3 灵活性

  3.3.3 输入输出要求

  3.3.4 数据管理能力的要求

  3.3.5 故障处理要求

  3.3.6 其它的专门的要求

  3.4 运行环境规定

  3.4.1 设备

  3.4.2 支持软件

  3.4.3 接口

  3.4.4 控制

4 数据需求说明书

数据要求说明书的编制目的是为了向整个开发时期提供关于处理数据的描述和数据采集要求的技术信息。编制数据要求说明书的内容要求如下:

  4.1 引言

  4.1.1 编写目的

  4.1.2 背景

  4.1.3 定义

  4.1.4 参考资料

  4.2 数据的逻辑描述

  4.2.1 静态数据

  4.2.2 动态输入数据

  4.2.3 动态输出数据

  4.2.4 内部生成数据

  4.2.5 数据约定

  4.3 数据的采集

  4.3.1 要求和范围

  4.3.2 输入的承担者

  4.3.3 处理

  4.3.4 影响

5 概要设计说明书

概要设计说明书可称作系统设计说明书,这里说的系统是指程序系统,编制的目的是说明对程序的系统的设计考虑,包括程序系统的基本处理流程、程序系统的组织结构、模块划分、功能分配、接口设计、运行设计、数据结构设计和出错处理设计等,为程序的详细设计提供基础。编制概要设计说明书的内容要求如下:

  5.1 引言

  5.1.1 编写目的

  5.1.2 背景

  5.1.3 定义

  5.1.4 参考资料

  5.2 总体设计

  5.2.1 需求规定

  5.2.2 运行环境

  5.2.3 基本设计概念和处理流程

  5.2.4 结构

  5.2.5 功能需求与程序的关系

  5.2.6 人工处理过程

  5.2.7 尚未解决的问题

  5.3 接口设计

  5.3.1 用户接口

  5.3.2 内部接口

  5.3.3 外部接口

  5.4 运行设计

  5.4.1 运行模块组合

  5.4.2 运行控制

  5.4.3 运行时间

  5.5 系统数据结构设计

  5.5.1 逻辑结构设计要点

  5.5.2 物理结构设计要点

  5.5.3 数据结构与程序的关系

  5.6 系统出错处理设计

  5.6.1 出错信息

  5.6.2 补救措施

  5.6.3 系统维护设计

6 详细设计说明书

详细说明书可称作程序设计说明书。编制目的是说明一个软件系统各个层次中的每一个程序(每个模块或子程序)的设计考虑,如果一个软件系统比较简单,层次很少,本文件可以不单独编写,有关内容合并概要设计说明书。对详细设计说明书的内容要不得要求如下:

  6.1 引言

  6.1.1 编写目的

  6.1.2 背景

  6.1.3 定义

  6.1.4 参考资料

  6.2 程序系统的组织结构

  6.3 程序1(标识符)设计说明

  6.3.1 程序描述

  6.3.2 功能

  6.3.3 性能

  6.3.4 输入项

  6.3.5 输出项

  6.3.6 算法

  6.3.7 流程逻辑

  6.3.8 接口

  6.3.9 存储分配

  6.3.10 注释设计

  6.3.11 限制条件

  6.3.12 测试计划

  6.3.13 尚未解决的问题

  6.4 程序2(标识符)设计说明

  ……

7 数据库设计说明书

数据库设计说明书的编制目的是对于设计中的数据库所有标识、逻辑结构和理结构作出具体的设计规定。其内容要求如下:

  7.1 引言

  7.1.1 编写目的

  7.1.2 背景

  7.1.3 定义

  7.1.4 参考资料

  7.2 外部设计

  7.2.1 标识符和状态

  7.2.2 使用它的程序

  7.2.3 约定

  7.2.4 专门指导

  7.2.5 支持软件

  7.3 结构设计

  7.3.1 概念结构设计

  7.3.2 逻辑结构设计

  7.3.3 理结构设计

  7.4 运用设计

  7.4.1 数据字典设计

  7.4.2 安全保密设计

8 用户手册

用户手册的编制是要使用非专门术语的语言,充分地描述该软件系统工程所具有的功能及基本的使用方法。使用户(或潜在用户)通过本手册能够了解该软件的用途,并且能够确定在什么情况下,如何使用它。具体的内容要求如下:

  8.1 引言

  8.1.1 编写目的

  8.1.2 背景

  8.1.3 定义

  8.1.4 参考资料

  8.2 用途

  8.2.1 功能

  8.2.2 性能

  8.2.2.1 精度

  8.2.2.2 时间特性

  8.2.2.3 灵活性

  8.2.3 安全保密

  8.3 运行环境

  8.3.1 硬设备

  8.3.2 支持软件

  8.3.3 数据结构

  8.4 使用过程

  8.4.1 安装与初始化

  8.4.2 输入

  8.4.2.1 输入数据的现实背景

  8.4.2.2 输入格式

  8.4.2.3 输入举例

  8.4.3 输出

  8.4.3.1 输出数据的现实背景

  8.4.3.2 输出格式

  8.4.3.3 输出举例

  8.4.4 文卷查询

  8.4.5 出错处理与恢复

  8.4.6 终端操作

9 操作手册

操作手册的编制是为了向操作人中提供该软件每一个运行的具体过程和有关知识,包括操作方法的细节。具体的内容要求如下:

  9.1 引言

  9.1.1 编写目的

  9.1.2 背景

  9.1.3 定义

  9.1.2 参考资料

  9.2 软件概述

  9.2.1 软件的结构

  9.2.2 程序表

  9.2.3 文卷表

  9.3 安装与初始化

  9.4 运行说明

  9.4.1 运行表

  9.4.2 运行步骤

  9.4.3 运行1(标识符)说明

  9.4.3.1 运行控制

  9.4.3.2 操作信息

  9.4.3.3 输入-输出文卷

  9.4.3.4 输出文段

  9.4.3.5 输出文段的复制

  9.4.3.6 启动恢复过程

  9.4.4 运行2(标识符)说明

  9.5 非常规过程

  9.6 远程操作

10 模块开发卷宗

  模块开发卷宗是在模块开发过程中逐步编写出来的,每完成一个模块或一级密切相关的模块的复审时编写一份,应该把所有的模块开发卷宗汇集在一起。编写的目的是记录和汇总低层次开发的进度和结果,以便于对整个模块开发工作的管理和复审,并为将来的维护提供非常有用的技术信息。具体的内容要求如下:

  10.1 标题

  10.2 模块开发情况表

  10.3 功能说明

  10.4 设计说明

  10.5 源代码清单

  10.6 测试说明

  10.7 复审的结论

11 测试计划

  11.1 引言

  11.1.1 编写目的

  11.1.2 背景

  11.1.3 定义

  11.1.4 参考资料

  11.2 计划

  11.2.1 软件说明

  11.2.2 测试内容

  11.2.3 测试1(标识符)

  11.2.3.1 进度安排

  11.2.3.2 条件

  11.2.3.3 测试资料

  11.2.3.4 测试培训

  11.2.4 测试2(标识符)

  ……

  11.3 测试设计说明

  11.3.1 测试1(标识符)

  11.3.1.1 控制

  11.3.1.2 输入

  11.3.1.3 输出

  11.3.1.4 过程

  11.3.2 测试2(标识符)

  ……

  11.4 评价准则

  11.4.1 范围

  11.4.2 数据整理

  11.4.3 尺度

12 测试分析报告

测试分析报告的编写是为了把组装测试和确认测试的结果、发现及分析写成文件加发记载,具体的编写内容要求如下:

  12.1 引言

  12.1.1 编写目的

  12.1.2 背景

  12.1.3 定义

  12.1.4 参考资料

  12.2 测度概要

  12.3 测试结果及发现

  12.3.1 测试1(标识符)

  12.3.2 测试2(标识符)

  ……

  12.4 对软件功能的结论

  12.4.1 功能1(标识符)

  12.4.1.1 能力

  12.4.1.2 限制

  12.4.2 功能2(标识符)

  ……

  12.5 分析摘要

  12.5.1 能力

  12.5.2 缺陷和限制

  12.5.3 建议

  12.5.4 评价

  12.6 测试资源消耗

13 开发进度月报

开发进度月报的编制目的是及时向有关管理部门汇报项目开发的进展和情况,以便函及时发现或处理开发过程中出现的问题。一般地,开发进度月报是以项目组为单位每月编写的。如果被开发的软件系统规模比较大,整个工程项目被划分给若干个分项目组承担,开发进度月报将以项目组为单位按月编写。具体的内容要求如下:

  13.1 标题

  13.2 工程进度与状态

  13.2.1 进度

  13.2.2 状态

  13.3 资源耗用与状态

  13.3.1 资源耗用

  13.3.1.1 工时

  13.3.1.2 机时

  13.3.2 状态

  13.4 经费支出与状态

  13.4.1 经费支出

  13.4.1.1 支持性费用

  13.4.1.2 设备购置费

  13.4.2 状态

  13.5 下个月的工作计划

  13.6 建议

14 项目开发总结报告

项目开发总结报告的编制是为了总结本项目开发工作的经验,说明实际取得的开发结果以及对整个开发工作的各个方面的评价。具体的内容要求如下:

  14.1 引言

  14.1.1 编写目的

  14.1.2 背景

  14.1.3 定义

  14.1.4 参考资料

  14.2 实际开发结果

  14.2.1 产品

  14.2.2 主要功能和性能

  14.2.3 基本流程

  14.2.4 进度

  14.2.5 费用

  14.3 开发工作评价

  14.3.1 对生产效率的评价

  14.3.2 对产品质量的评价

  14.3.3 对技术方法的评价

  14.3.4 出错原因的分析

相关推荐