计算机操作系统实验课程教案文档格式.docx
《计算机操作系统实验课程教案文档格式.docx》由会员分享,可在线阅读,更多相关《计算机操作系统实验课程教案文档格式.docx(69页珍藏版)》请在冰点文库上搜索。
验证型
课时安排
教学
目的
▪熟悉操作系统进程管理的概念
▪初步理解WindowsXP进程的编程
预习
要求
教
学
内
容
与
过
程
实验内容1Windows任务管理器的进程管理(30分钟)
1、背景知识简介
▪Windows的任务管理器提供了用户计算机上正在运行的程序和进程的相关信息,也显示了最常用的度量进程性能的单位
▪使用任务管理器
•可以打开监视计算机性能的关键指示器,快速查看正在运行的程序的状态,或者终止已停止响应的程序
•也可以使用多个参数评估正在运行的进程的活动,以及查看CPU和内存使用情况的图形和数据
▪任务管理器中
•“应用程序”选项卡:
显示正在运行程序的状态,用户能够结束、切换或者启动程序
•“进程”选项卡:
显示正在运行的进程信息。
例如,可以显示关于CPU和内存使用情况、页面错误、句柄计数以及许多其他参数的信息
•“性能”选项卡:
显示计算机动态性能,包括CPU和内存使用情况的图表,正在运行的句柄、线程和进程的总数,物理、核心和认可的内存总数(KB)等
2、实验目的和要求
▪通过在Windows任务管理器中对程序进程进行响应的管理操作
▪学习观察操作系统运行的动态性能
3、实验环境
▪需要准备一台运行WindowsXPProfessional操作系统的计算机
4、实验内容与步骤
▪使用任务管理器终止进程
▪显示其他进程记数器
▪更改正在运行的程序的优先级
5、实验提示
▪注意实验中所使用的是操作系统的哪个版本
▪了解在当前机器中正在运行的应用程序
▪在WindowsXP的任务管理器中,“进程”选项卡增加了一个“用户名”栏目,其中区分了SYSTEM、NETWORKSERVICE、LOCALSERVICE和用户的不同进程类别
▪终止进程时要小心,有可能导致不希望发生的结果,包括数据丢失和系统不稳定等;
终止进程树将结束该进程以及它直接或间接创建的所有子进程
实验内容2Windows进程编程(60分钟)
▪Windows可以识别的应用程序包括控制台应用程序、GUI应用程序和服务应用程序
▪控制台应用程序可以创建GUI;
GUI应用程序可以作为服务来运行;
服务也可以向标准的输出流写入数据——不同类型应用程序间的惟一重要区别是其启动方法
▪WindowsXP是以NT的技术构建的,它提供了创建控制台应用程序的能力,使用户可以利用标准的C++工具,如iostream库中的cout和cin对象,来创建小型应用程序。
当系统运行时,WindowsXP的服务通常要向系统用户提供所需功能
▪服务应用程序类型需要ServiceMail()函数,由服务控制管理器(SCM)加以调用。
SCM是操作系统的集成部分,负责响应系统启动以开始服务、指导用户控制或从另一个服务中来的请求。
其本身负责使应用程序的行为像一个服务。
通常,服务登录到特殊的LocalSystem账号下,此账号具有与开发人员创建的服务不同的权限
▪当令C++编译器创建可执行程序时,编译器将源代码编译成OBJ文件,然后将其与标准库相链接。
产生的EXE文件是装载器指令、机器指令和应用程序的数据的集合。
装载器指令告诉系统从哪里装载机器代码。
另一个装载器指令告诉系统从哪里开始执行进程的主线程。
在进行某些设置后,进入开发者提供的main()、ServiceMain()或WinMain()函数的低级入口点。
机器代码中包括有控制逻辑,它所做的事包括跳转到WindowsAPI函数,进行计算或向磁盘写入数据等
▪Windows允许开发人员将大型应用程序分为较小的、互相有关系的服务模块,即动态链接库(DLL)代码块,在其中包含应用程序所使用的机器代码和应用程序的数据
▪Windows所创建的每个进程都从调用CreateProcess()API函数开始,该函数的任务是在对象管理器子系统内初始化进程对象
▪每一进程都以调用ExitProcess()或TerminateProcess()API函数终止。
通常应用程序的框架负责调用ExitProcess()函数。
对于C++运行库来说,这一调用发生在应用程序的main()函数返回之后
▪创建进程
•CreateProcess()调用的核心参数是可执行文件运行时的文件名及其命令行
▪正在运行的进程
•如果一个进程拥有至少一个执行线程,则为正在系统中运行的进程。
通常,这种进程使用主线程来指示它的存在。
当主线程结束时,调用ExitProcess()API函数,通知系统终止它所拥有的所有正在运行、准备运行或正在挂起的其他线程
•当进程正在运行时,可以通过一系列的API函数来查看它的许多特性,其中少数特性也允许加以修改
▪终止进程
•所有进程都是以调用ExitProcess()或者TerminateProcess()函数结束的。
但最好使用前者而不要使用后者,因为进程是在完成了它的所有的关闭“职责”之后以正常的终止方式来调用前者的。
而外部进程通常调用后者即突然终止进程的进行,由于关闭时的途径不太正常,有可能引起错误的行为
▪TerminateProcess()API函数只要打开带有PROCESS_TERMINATE访问权的进程对象,就可以终止进程,并向系统返回指定的代码。
这是一种“野蛮”的终止进程的方式,但是有时却是需要的
▪通过对Windows进程编程
•进一步熟悉操作系统的基本概念
•进一步熟悉进程的概念
•初步理解Windows进程的编程
▪通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解Windows进程的“一生”
▪通过阅读和分析实验程序,学习创建进程、观察进程和终止进程的程序设计方法
▪需要做以下准备
•一台运行WindowsXPProfessional操作系统的计算机
•计算机中需安装VisualC++开发环境(版本不限)
1、启动VisualC++,新建一个空的Win32ConsoleApplication,工程名为xxProcHandle,其中“xx”为你的姓名拼音首字母+学号末两位,如张三学号末两位为21,则其工程名为ZS21ProcHandle。
2、新建一个cpp文件,文件名任意,输入以下代码(边输入边理解代码):
3、增加代码,实现更改并显示当前运行进程的优先级(更改为何种优先级由用户选择)
提示:
使用SetPriorityClass,其原型为:
BOOLWINAPISetPriorityClass(
HANDLEhProcess,//进程句柄
DWORDdwPriorityClass//优先级(取值和GetPriorityClass获取到的优先级一样,包括HIGH_PRIORITY_CLASS等等)
);
4、新建一个空的Win32ConsoleApplication,工程名为xxProcList,其中“xx”为你的姓名拼音首字母+学号末两位。
5、新建一个cpp文件,输入以下代码:
#include<
windows.h>
tlhelp32.h>
iostream>
usingnamespacestd;
//根据用户模式及内核模式下的消耗时间,计算在内核模式下进程所耗时间百分数
DWORDGetKernelModePercentage(constFILETIME&
ftKernel,constFILETIME&
ftUser)
{
//将FILETIME结构转化为位整数
ULONGLONGqwKernel=(((ULONGLONG)ftKernel.dwHighDateTime)<
<
32)+ftKernel.dwLowDateTime;
ULONGLONGqwUser=(((ULONGLONG)ftUser.dwHighDateTime)<
32)+ftUser.dwLowDateTime;
//将消耗时间相加,然后计算消耗在内核模式下的时间百分比
ULONGLONGqwTotal=qwKernel+qwUser;
if(qwTotal>
0)//防止除0
return(DWORD)(((ULONGLONG)100*qwKernel)/qwTotal);
else
return0;
}
//以下是将当前正在运行的所有进程名和消耗在内核模式下的时间百分数都显示出来的应用程序
voidmain()
//对当前系统中运行的进程拍取"
快照"
HANDLEhSnapshot=CreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS,//提取进程快照
0);
//进程ID,当前进程设置为(前一参数为TH32CS_SNAPPROCESS时忽略此参数)
//初始化进程信息项结构体
PROCESSENTRY32pe;
ZeroMemory(&
pe,sizeof(pe));
//将pe的成员全部初始化为0
pe.dwSize=sizeof(pe);
//调用Process32First前必须设置PROCESSENTRY32中的dwSize成员
//获得第一个进程信息
BOOLbMore=Process32First(hSnapshot,&
pe);
//获取成功返回TRUE,否则返回FALSE
while(bMore)//只要快照中还有进程未处理,则继续循环
{
//打开用于读取的进程
HANDLEhProcess=OpenProcess(
PROCESS_QUERY_INFORMATION,//指明打开进程是为了得到进程信息
FALSE,//当前进程的子进程不能继承这一句柄
pe.th32ProcessID);
//要打开的进程ID
if(hProcess!
=NULL)
{
//查询进程的时间信息
FILETIMEftCreation,ftKernelMode,ftUserMode,ftExit;
GetProcessTimes(
hProcess,//所感兴趣的进程句柄
&
ftCreation,//进程的启动时间
ftExit,//结束时间(如果有的话)
ftKernelMode,//在内核模式下消耗的时间
ftUserMode);
//在用户模式下消耗的时间
//计算内核模式消耗的时间百分比
DWORDdwPctKernel=GetKernelModePercentage(
ftKernelMode,//在内核模式上消耗的时间
ftUserMode);
//向用户显示进程的某些信息
cout<
"
processID:
<
pe.th32ProcessID
<
EXEfile:
"
pe.szExeFile
inKernelmode:
dwPctKernel
%"
endl;
//关闭句柄
CloseHandle(hProcess);
}
//获取快照中下一个进程
bMore=Process32Next(hSnapshot,&
}
该代码参照计算机的任务管理器中的进程栏所列出的内容,列出当前系统所有运行进程及其相关信息。
理解上述代码。
6、添加代码,同时显示进程的其他信息(提示:
在MSDN中查询PROCESSENTRY32,了解该结构体中还有哪些信息,将其显示出来,另外可查找GetProcess,有一些以GetProcess开头的函数,比如GetProcessMemoryInfo,可以获取进程的内存相关信息)
7、添加代码实现功能:
对列出的所有的进程,可以改变所选进程的优先级。
(提示:
由用户键入ID,和输入设置的优先级,设置优先级时需要进程句柄,可通过OpenProcess函数得到,第一个参数使用PROCESS_ALL_ACCESS)
8、新建一个空的Win32ConsoleApplication,工程名为xxProcCreate,其中“xx”为你的姓名拼音首字母+学号末两位。
新建一个cpp文件,输入以下代码
//通过进程创建克隆本进程
stdio.h>
//创建传递过来的进程的克隆进程并赋于其ID值
voidStartClone(intnCloneID)
//提取用于当前可执行文件的文件名
TCHARszFilename[MAX_PATH];
//第一个参数为NULL表示提取的是本进程的文件名
GetModuleFileName(NULL,szFilename,MAX_PATH);
//格式化用于子进程的命令行并通知其克隆ID
TCHARszCmdLine[MAX_PATH];
sprintf(szCmdLine,"
%d"
nCloneID);
//用于子进程的STARTUPINFO结构
STARTUPINFOsi;
ZeroMemory((void*)(&
si),sizeof(si));
si.cb=sizeof(si);
//必须是本结构的大小
//返回的用于子进程的进程信息
PROCESS_INFORMATIONpi;
//利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质
BOOLbCreateOK=CreateProcess(
szFilename,//产生这个EXE的应用程序的名称
szCmdLine,//命令行参数
NULL,//缺省的进程安全性
NULL,//缺省的线程安全性
FALSE,//不继承句柄
CREATE_NEW_CONSOLE,//使用新的控制台
NULL,//新的环境,为NULL表示使用和当前进程相同的环境
NULL,//当前目录与当前进程相同
&
si,//启动信息
pi);
//返回的进程信息
//释放对子进程的引用
if(bCreateOK)
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
intmain(intargc,char*argv[])
//确定进程在列表中的位置
intnClone=0;
charfileName[MAX_PATH];
//存放文件名
if(argc>
0)//有命令行参数?
//从第1个参数中提取克隆ID
sscanf(argv[0],"
&
nClone);
//显示进程位置
cout<
ProcessID:
GetCurrentProcessId()
<
CloneID:
nClone
//检查是否有创建子进程的需要
constintc_nCloneMax=25;
//克隆次数
if(nClone<
c_nCloneMax)
//发送新进程的命令行和克隆号
StartClone(++nClone);
//在终止之前暂停一下(2000毫秒,即2秒)
Sleep(2000);
return0;
理解上述代码,通过查询MSDN或网络,了解相关API函数的用法。
9、(可选)修改上述程序为一个恶作剧程序(不断弹出新的控制台窗口)。
10、新建一个空的Win32ConsoleApplication,工程名为xxProcVersion,其中“xx”为你的姓名拼音首字母+学号末两位。
//version项目
//利用进程和操作系统的版本信息的简单示例
//提取这个进程的ID
DWORDdwIdThis=GetCurrentProcessId();
//获得进程运行所需系统的版本,也可以传递参数以便指明是当前进程
DWORDdwVerReq=GetProcessVersion(dwIdThis);
WORDwMajorReq=(WORD)(dwVerReq>
>
16);
WORDwMinorReq=(WORD)(dwVerReq&
0xffff);
dwIdThis
requiresOS:
wMajorReq<
."
wMinorReq<
//设置版本信息的数据结构,以便保存操作系统的版本信息
OSVERSIONINFOEXosvix;
osvix,sizeof(osvix));
osvix.dwOSVersionInfoSize=sizeof(osvix);
//获取版本信息并输出报告
GetVersionEx((LPOSVERSIONINFO)&
osvix);
RunningonOS:
osvix.dwMajorVersion<
osvix.dwMinorVersion<
//如果是NT系统,则提高其优先权
if(osvix.dwPlatformId==VER_PLATFORM_WIN32_NT&
&
osvix.dwMajorVersion>
=5)
//改变优先级
SetPriorityClass(
GetCurrentProcess(),//获取当前进程句柄
HIGH_PRIORITY_CLASS);
//改变为high
//报告给用户
TaskManagershouldnowindicatethis"
"
processishighpriority."
getchar();
11、进阶:
编写一个类似于任务管理器的应用程序。
时间分配:
1.演示和讲解(15分钟)
实验(75分钟)
后记
注:
“教学后记”为可选填写项,是授课完毕后,教师对授课准备情况、授课过程及授课效果的回顾与总结。
了解Windows中的进程和线程,了解多线程编程,理解基于互斥对象的线程同步的实现。
进程(线程)同步控制基本概念与方法
Windows多线程编程方法
查阅相关函数CreateMutex,ReleaseMutex,WaitForSingleObject
一、实验目的
了解Windows中的进程和线程,了解多线程编程,理解基于互斥对象的线程同步的实现。
二、实验环境
Windows操作系统
VisualC++编程环境
三、实验要求
跟着实验指导书步骤边做边思考,同时完成实验报告(非正式,无格式要求,但须按指导书要求列出相关内容),在下次实验前提交到指定的邮箱(可不用交程序)。
四、实验步骤:
1、新建一个空的Win32ConsoleApplication类型的工程,工程取名为:
xxMultiThread,其中“xx”为你的姓名拼音首字母+学号末两位,如张三学号末两位为21,则其工程名为ZS21MultiThread。
2、为该工程添加一个C++源文件:
MultiThread.cpp。
然后添加如下图所示代码:
3、理解上述代码,关键点:
a)CreateThread:
WindowsAPI函数,用于创建线程,将本程序中CreateThread参数取值含义写入实验报告中。
b)CloseHandle:
WindowsAPI函数,用于关闭新线程的句柄。
刚创建了为何要关闭呢?
注意:
调用CloseHandle并没有中止新创建线程,只是表示在主线程中对新创建的线程的引用不感兴趣,因此将它关闭。
该函数会递减该线程的引用计数,当线程引用计数为0时,系统会释放该线程内核对象。
c)线程入口函数(Fun1Proc)的原型是固定的,但名称可以改动,函数原型可通过查MSDN获得,不需死记硬背。
4、编译运行该程序(使用Ctrl+F5),运行多次,将运行结果截图放入实验报告。
如果是多核CPU,结果可能是只输出了“mainthreadisrunning”,也可能是两句话都输出了,还可能是在输出了“mainthreadisrunning”的同时第二句只输出了一部分;
对于单核CPU,应该只输出了“mainthreadisrunning”。
如果你的机器始终