操作系统实验指导书春季学期.docx
- 文档编号:23416018
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:89
- 大小:55.82KB
操作系统实验指导书春季学期.docx
《操作系统实验指导书春季学期.docx》由会员分享,可在线阅读,更多相关《操作系统实验指导书春季学期.docx(89页珍藏版)》请在冰豆网上搜索。
操作系统实验指导书春季学期
操作系统实验指导书
计算机科学与软件学院
2015年
实验一进程控制与描述
一、实验目的
通过对WindowsXP编程,进一步熟悉操作系统的基本概念,较好地理解WindowsXP的结构。
通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解WindowsXP进程的“一生”。
二、实验环境
硬件环境:
计算机一台,局域网环境;
软件环境:
WindowsXP,VisualC++6.0专业版或企业版。
三、实验内容和步骤
第一部分Windows编程
WindowsXP可以识别的程序包括控制台应用程序、GUI应用程序和服务应用程序。
本实验中主要用到的是控制台应用程序和GUI应用程序。
1、简单的控制台应用程序
创建一个名为“Hello”的应用程序,在“开始”菜单中单击“程序”-“附件”-“记事本”命令,将程序键入记事本中,并把代码保存为1-1.cpp。
程序1-1WindowsXP的GUI应用程序
#include
voidmain()
{
Std:
:
cout<<”Hello,WindowsXP”< : endl; } 在“命令提示符”窗口运行CL.EXE,产生1-1.EXE文件: C: \>CL1-1.cpp 运行1-1.EXE程序,运行结果是: (如果运行不成功,则可能的原因是什么? ) ____________________________________________________________________ ____________________________________________________________________ 2、GUI应用程序 WindowsXPProfessional下的GUI应用程序,使用VisualC++编译器创建一个GUI应用程序,代码中包括了WinMain()方法,该方法GUI类型的应用程序的标准入口点。 在“开始”菜单中单击“程序”-“附件”-“记事本”命令,将程序键入记事本中,并把代码保存为1-2.cpp。 程序1-2WindowsXP的GUI应用程序 //msgbox项目 #include //告诉连接器与包括MessageBoxAPI函数的user32库进行连接 #pragmacomment(lib,“user32.lib”) //这是一个可以弹出信息框然后退出的筒单的应用程序 intAPIENTRYWinMain(HINSTANCE/*hInstance*/, HINSTANCE/*hPrevInstance*/, LPSTR/*lpCmdLine*/, int/*nCmdShow*/) { : : MessageBox( NULL,//没有父窗口 “Hello,Windows2000”,//消息框中的文本 “Greetings”,//消息框标题 MB_OK);//其中只有一个OK按钮 //返回0以便通知系统不进入消息循环 return(0); } 也可以利用任何其他文本编辑器键入程序代码,如果这样,例如使用WORD来键入和编辑程序,则应该注意什么问题? ____________________________________________________________________ ____________________________________________________________________ 在“命令提示符”窗口运行CL.EXE,产生1-2.EXE文件: C: \>CL1-2.cpp 在程序1-2的GUI应用程序中,首先需要Windows.h头文件,以便获得传送给WinMain()和MessageBox()API函数的数据类型定义。 接着的pragma指令指示编译器/连接器找到User32.LIB库文件并将其与产生的EXE文件连接起来。 这样就可以运行简单的命令行命令CLMsgBox.CPP来创建这一应用程序,如果没有pragma指令,则MessageBox()API函数就成为未定义的了。 这一指令是VisualStudioC++编译器特有的。 接下来是WinMain()方法。 其中有四个由实际的低级入口点传递来的参数。 hInstance参数用来装入与代码相连的图标或位图一类的资源,无论何时,都可用GetModuleHandle()API函数将这些资源提取出来。 系统利用实例句柄来指明代码和初始的数据装在内存的何处。 句柄的数值实际上是EXE文件映像的基地址,通常为0x00400000。 下一个参数hPrevInstance是为向后兼容而设的,现在系统将其设为NULL。 应用程序的命令行(不包括程序的名称)是lpCmdLine参数。 另外,系统利用nCmdShow参数告诉应用程序如何显示它的主窗口(选项包括最小化、最大化和正常)。 最后,程序调用MessageBox()API函数并退出。 如果在进入消息循环之前就结束运行的话,最后必须返回0。 运行结果(试将其中的信息与程序1-1.EXE的运行结果进行比较): _____________________________________________________________________________ ________________________________________________________________________ ________________________________________________________________________ ________________________________________________________________________ 3、进程对象 操作系统将当前运行的应用程序看作是进程对象。 利用系统提供的惟一的称为句柄(HANDLE)的号码,就可与进程对象交互。 这一号码只对当前进程有效。 本实验表示了一个简单的进程句柄的应用。 在系统中运行的任何进程都可调用GetCurrentProcess()API函数,此函数可返回标识进程本身的句柄。 然后就可在Windows需要该进程的有关情况时,利用这一句柄来提供。 程序1-3: 获得和使用进程的句柄 //prochandle项目 #include #include //确定自己的优先权的简单应用程序 voidmain() { //从当前进程中提取句柄 HANDLEhProcessThis=: : GetCurrentProcess(); //请求内核提供该进程所属的优先权类 DWORDdwPriority=: : GetPriorityClass(hProcessThis); //发出消息,为用户描述该类 std: : cout<<“Currentprocesspriority: ”; switch(dwPriority) { caseHIGH_PRIORITY_CLASS: std: : cout<<“High”; break; caseNORMAL_PRIORITY_CLASS: std : : cout<< “Normal”; break; caseIDLE_PRIORITY_CLASS: std: : cout<<“Idle”; break; caseREALTIME_PRIORITY_CLASS: std: : cout<<“Realtime”; break; default: std: : cout<<“ break; } std: : cout< : endl; } 程序1-3中列出的是一种获得进程句柄的方法。 对于进程句柄可进行的惟一有用的操作是在API调用时,将其作为参数传送给系统,正如程序1-3中对GetPriorityClass()API函数的调用那样。 在这种情况下,系统向进程对象内“窥视”,以决定其优先级,然后将此优先级返回给应用程序。 OpenProcess()和CreateProcess()API函数也可以用于提取进程句柄。 前者提取的是已经存在的进程的句柄,而后者创建一个新进程,并将其句柄提供出来。 在“命令提示符”窗口运行CL.EXE,产生1-3.EXE文件: C: \>CL1-3.cpp 运行结果: __________________________________________________________ ________________________________________________________________________ ________________________________________________________________________ 将程序1-4.cpp程序键入记事本中,并把代码保存为1-4.cpp。 程序1-4显示如何找出系统中正在运行的所有进程,如何利用OpenProcess()API函数来获得每一个访问进程的进一步信息。 程序1-4利用句柄查出进程的详细信息 //proclist项目 #include #include #include //当在用户模式机内核模式下都提供所耗时间时,在内核模式下进行所耗时间的64位计算的帮助方法 DWORDGetKernelModePercentage(constFILETIME&ftKernel, constFILETIME&ftUser) { //将FILETIME结构转化为64位整数 ULONGLONGqwKernel= (((ULONGLONG)ftKernel.dwHighDateTime)<<32)+ ftKernel.dwLowDateTime; ULONGLONGqwUser= (((ULONGLONG)ftUser.dwHighDateTime)<<32)+ ftUser.dwLowDateTime; //将消耗时间相加,然后计算消耗在内核模式下的时间百分比 ULONGLONGqwTotal=qwKernel+qwUser; DWORDdwPct= (DWORD)(((ULONGLONG)100*qwKernel)/qwTotal); return(dwPct); } //以下是将当前运行进程名和消耗在内核模式下的时间百分数都显示出来的应用程序 voidmain() { //对当前系统中运行的进程拍取“快照” HANDLEhSnapshot=: : CreateToolhelp32Snapshot( TH32CS–SNAPPROCESS,//提取当前进程 0);//如果是当前进程,就将其忽略 //初始化进程入口 PROCESSENTRY32pe; : : ZeroMemory(&pe,sizeof(pe)); pe.dwSize=sizeof(pe); //按所有进程循环 BOOLbMore=: : Process32First(hSnapshot,&pe); while(bMore) { //打开用于读取的进程 HANDLEhProcess=: : OpenProcess( PROCESS_QUERY_INFORMATION,//指明要得到信息 FALSE,//不必继承这一句柄 pe.th32ProcessID);//要打开的进程 if(hProcess! =NULL) { //找出进程的时间 FILETIMEftCreation,ftExit,ftKernelMode,ftUserMode; : : GetProcessTimes( hProcess,//所感兴趣的进程 &ftCreation,//进程的启动时间(绝对的) &ftExit,//结束时间(如果有的话) &ftKernelMode,//在内核模式下消耗的时间 &ftUserMode);//在用户模式下消耗的时间 //计算内核模式消耗的时间百分比 DWORDdwPctKernel=: : GetKernelModePercentage( ftKernelMode,//在内核模式上消耗的时间 ftUserMode);//在用户模式下消耗的时间 //向用户显示进程的某些信息 std: : cout<<“ProcessID: ”< <<“,EXEfile: ”< <<“,%inkernelmode: ”< < : endl; //消除句柄 : : CloseHandle(hProcess); } //转向下一个进程 bMore=: : Process32Next(hSnapshot,&pe); } } 程序1-4程序首先利用WindowsXP的新特性,即工具帮助库来获得当前运行的所有进程的快照。 然后应用程序进入快照中的每一个进程,得到其以PROCESSENTRY32结构表示的属性。 这一结构用来向OpenProcess()API函数提供进程的ID。 Windows跟踪每一进程的有关时间,示例中是通过打开的进程句柄和GetProcessTimes()API来直询得到有关时间的。 接下来,一个定制的帮助函数取得了几个返回的数值,然后计算进程在内核模式下消耗的时间占总时间的百分比。 程序的其余部分比较简单,只是将有关信息显示给用户,清除进程句柄,然后继续循环,直到所有进程都计算过为止。 在“命令提示符”窗口运行CL.EXE,产生1-4.EXE文件: C: \>CL1-4.cpp 运行结果: __________________________________________________________ ________________________________________________________________________ 第二部分: 进程的“一生” Windows所创建的每个进程都从调用CreateProcess()API函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。 每一进程都以调用ExitProcess()或TerminateProcess()API函数终止。 通常应用程序的框架负责调用ExitProcess()函数。 对于C++运行库来说,这一调用发生在应用程序的main()函数返回之后。 1、创建子进程 本实验显示了创建子进程的基本框架。 该程序创建的子进程依然执行父进程的程序代码,显示它的系统进程ID和它在进程列表中的位置。 创建子进程 //proccreate项目 #include #include #include //创建传递过来的进程的克隆过程并赋于其ID值 voidStartClone(intnCloneID) { //提取用于当前可执行文件的文件名 TCHARszFilename[MAX_PATH]; : : GetModuleFileName(NULL,szFilename,MAX_PATH); //格式化用于子进程的命令行并通知其EXE文件名和克隆ID TCHARszCmdLine[MAX_PATH]; : : sprintf(szCmdLine,“\”%s\”%d”,szFilename,nCloneID); //用于子进程的STARTUPINFO结构 STARTUPINFOsi; : : ZeroMemory(reinterpret_cast si.cb=sizeof(si);//必须是本结构的大小 //返回的用于子进程的进程信息 PROCESS_INFORMATIONpi; //利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质 BOOLbCreateOK=: : CreateProcess( szFilename,//产生这个EXE的应用程序的名称 szCmdLine,//告诉其行为像一个子进程的标志 NULL,//缺省的进程安全性 NULL,//缺省的线程安全性 FALSE,//不继承句柄 CREATE_NEW_CONSOLE,//使用新的控制台 NULL,//新的环境 NULL,//当前目录 &si,//启动信息 &pi);//返回的进程信息 //对子进程释放引用 if(bCreateOK) { : : CloseHandle(pi.hProcess); : : CloseHandle(pi.hThread); } } intmain(intargc,char*argv[]) { //确定进程在列表中的位置 intnClone(0); if(argc>1) { //从第二个参数中提取克隆ID : : sscanf(argv[1],“%d”,&nClone); } //显示进程位置 std: : cout<<“ProcessID: “<<: : GetCurrentProcessId() <<“,CloneID: “< < : endl; //检查是否有创建子进程的需要 constintc_nCloneMax=25; if(nClone { //发送新进程的命令行和克隆号 StartClone(++nClone); } //在终止之前暂停一下,输入一个字符后,程序结束,以便观察。 Std: : cout<<”inputachar: ”; getchar(); std: : cout<<”I‘mgone…Bye-bye”; : : Sleep(1000); return0; } 本程序展示的是一个简单的使用CreateProcess()API函数的例子。 首先形成简单的命令行,提供当前的EXE文件的指定文件名和代表生成克隆进程的号码。 大多数参数都可取缺省值,但是创建标志参数使用了: ________________________________________________________________________ 标志,指示新进程分配它自己的控制台,这使得运行示例程序时,在任务栏上产生许多活动标记。 然后该克隆进程的创建方法关闭传递过来的句柄并返回main()函数。 在关闭程序之前,每一进程的执行主线程都会暂停等待输入字符,以便让用户观察子进程的行为。 CreateProcess()函数有________个核心参数? 本实验程序中设置的各个参数的值的含义是: a._________________________________________________; b._________________________________________________; c._________________________________________________; d._________________________________________________; e._________________________________________________; f._________________________________________________; g._________________________________________________; h._________________________________________________; 程序运行时屏幕显示的信息是: ____________________________________________________________________ ________________________________________________________________________ 2、正在运行的进程 本实验的程序中列出了用于进程信息查询的API函数GetProcessVersion()与GetVersionEx()的共同作用,可确定运行进程的操作系统的版本号。 使用进程和操作系统的版本信息 //version项目 #include #include //利用进程和操作系统的版本信息的简单示例 voidmain() { //提取这个进程的ID号 DWORDdwIdThis=: : GetCurrentProcessId(); //获得这一进程和报告所需的版本,也可以发送0以便指明这一进程 DWORDdwVerReq=: : GetProcessVersion(dwIdThis); WORDwMajorReq=(WORD)dwVerReq>16); WORDwMinorReq=(WORD)dwVerReq&0xffff); std: : cout<<“ProcessID: “< <<“,requiresOS: “< : endl ; //设置版本信息的数据结构,以便保存操作系统的版本信息 OSVERSIONINFOEXosvix; : : ZeroMemory(&osvix,sizeof(osvix))
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 实验 指导书 春季 学期