计算机科学与技术、 信息管理和信息系统专业 《操作系统》实验指导书
《操作系统》实验指导书
实验一 Linux系统的安装
一、实验目的
1、深入认识磁盘分区
2、掌握Linux安装的基本过程 3、掌握多系统共存的系统安装方法 二、实验任务
在现有系统安装Redhat Linux系统,注意不要破坏现有系统。 三、实验指导
参考《Linux上机实践教程》第一章内容。
实验二 Linux系统的基本使用
一、实验目的
1、熟悉linux系统的启动、登入和退出 2、熟悉linux系统文件和目录的基本使用 3、熟悉其它常用命令及虚拟终端的使用 4、体会linux系统作为分时系统的特点 二、实验任务
启动、登入和退出linux系统
练习使用文件和目录操作的基本命令 使用它常用命令及虚拟终端 练习使用Vi编辑器 三、实验指导
参考《Linux上机实践教程》第二、三章内容。
实验三 windows 2000中进程的创建和控制
一、实验目的
1、加深对进程概念的理解,明确进程和程序的区别 2、进一步认识进程并发执行的实质
3、掌握windows 2000中进程创建和控制的编程方法 二、实验任务
2
《操作系统》实验指导书
创建一个windows窗口程序,含有4个菜单项,分别用来创建和撤消记事本进程和计算器进程。若相应进程已经创建了,再选择创建进程菜单,则弹出对话框提示进程已经创建;若进程已经撤消了,再选择撤消进程菜单,则弹出对话框提示进程已经撤消。注意考虑从主程序外部启动和关闭进程的情况。 三、实验指导
1、Win32的进程的概念
进程是应用程序的运行实例,由私有虚拟地址空间、代码、数据和其他操作系统资源(如进程创建的文件、管道、同步对象等)组成。一个应用程序可以有一个或多个进程,一个进程可以有一个或多个线程,其中一个是主线程。进程要完成什么事情的话必须至少拥有一个线程,由线程来负责执行包含在地址空间的代码。 2、Win32的进程的创建
Windows所创建的每个进程都从调用CreateProcess() API函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。CreateProcess() 调用的核心参数是可执行文件运行时的文件名及其命令行。下表详细地列出了每个参数的类型和名称。
表 CreateProcess() 函数的参数 参数名称 LPCTSTR lpApplivationName LPCTSTR lpCommandLine LPSECURIITY_ATTRIBUTES lpProcessAttributes LPSECURIITY_ATTRIBUTES lpThreadAttributes BOOL bInheritHandle DWORD dwCreationFlage LPVOID lpEnvironment LPCTSTR lpCurrentDirectory STARTUPINFO lpStartupInfo LPPROCESS_INFORMATION lpProcessInformation 使用目的 全部或部分地指明包括可执行代码的EXE文件的文件名 向可执行文件发送的参数 返回进程句柄的安全属性。主要指明这一句柄是否应该由其他子进程所继承 返回进程的主线程的句柄的安全属性 一种标志,告诉系统允许新进程继承创建者进程的句柄 特殊的创建标志 (如CREATE_SUSPENDED) 的位标记 向新进程发送的一套环境变量;如为null值则发送调用者环境 新进程的启动目录 STARTUPINFO结构,包括新进程的输入和输出配置的详情 调用的结果块;发送新应用程序的进程和主线程的句柄和ID
可以指定第一个参数,即应用程序的名称,其中包括相对于当前进程的当前目录的全路径或者利用搜索方法找到的路径;lpCommandLine参数允许调用者向新应用程序发送数据;接下来的三个参数与进程和它的主线程以及返回的指向该对象的句柄的安全性有关。
然后是标志参数,用以在dwCreationFlags参数中指明系统应该给予新进程什么行为。经常使用的标志是CREATE_SUSPNDED,告诉主线程立刻暂停。当准备好时,应该使用ResumeThread() API来启动进程。另一个常用的标志是CREATE_NEW_CONSOLE,告诉新进程启动自己的控制台窗口,而不是利用父窗口。这一参数还允许设置进程的优先级,用以向系统指明,相对于系统中所有其他的活动进程来说,给此进程多少CPU时间。
接着是CreateProcess() 函数调用所需要的三个通常使用缺省值的参数。第一个参数是lpEnvironment参数,指明为新进程提供的环境;第二个参数是lpCurrentDirectory,可用于向主创进程发送与缺省目录不同的新进程使用的特殊的当前目录;第三个参数是
3
STARTUPINFO数据结构所必需的,用于在必要时指明新应用程序的主窗口的外观。
CreateProcess() 的最后一个参数是用于新进程对象及其主线程的句柄和ID的返回值缓冲区。以PROCESS_INFORMATION结构中返回的句柄调用CloseHandle() API函数是重要的,因为如果不将这些句柄关闭的话,有可能危及主创进程终止之前的任何未释放的资源。 3、终止进程
所有进程都是以调用ExitProcess() 或者TerminateProcess() 函数结束的。但最好使用前者而不要使用后者,因为进程是在完成了它的所有的关闭“职责”之后以正常的终止方式来调用前者的。而外部进程通常调用后者即突然的进行,由于关闭时的途径不太正常,有可能引起错误的行为。
TerminateProcess() API函数只要打开带有PROCESS_TERMINATE访问权的进程对象,就可以终止进程,并向系统返回指定的代码。这是一种“野蛮”的终止进程的方式,但是有时却是需要的。 4、如何判断一个进程是否启动或终止?
如果一个进程的启动或终止完全由主进程控制,只需引入一个标志进行判断即可。如果外部可以控制进程的启动或终止,则情况要复杂一些。通常由两种方法,一是根据进程的程序名称,查询系统所有进程,以确定该程序是否已经运行。另一种方法是根据进程的窗口标题获得窗口句柄,再根据窗口句柄获得相应的程序名称,以确定该程序是否已经运行。以下是相关的API函数,可查阅MSDN: HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags, DWORD th32ProcessID );
BOOL WINAPI Process32First( HANDLE hSnapshot, LPPROCESSENTRY32 lppe ); BOOL WINAPI Process32Next( HANDLE hSnapshot, LPPROCESSENTRY32 lppe ); HWND FindWindow(
LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to window name);
UINT WINAPI GetWindowModuleFileName( HWND hwnd,
LPTSTR lpszFileName, UINT cchFileNameMax);
5、程序实例
本程序显示了创建子进程的基本框架。该程序只是再一次地启动自身,显示它的系统进程ID和它在进程列表中的位置。 # include
# include
// 创建传递过来的进程的克隆过程并赋于其ID值 void StartClone(int nCloneID) {
// 提取用于当前可执行文件的文件名 TCHAR szFilename[MAX_PATH] ;
:: GetModuleFileName(NULL, szFilename, MAX_PATH) ;
4
《操作系统》实验指导书
// 格式化用于子进程的命令行并通知其EXE文件名和克隆ID TCHAR szCmdLine[MAX_PATH] ;
:: sprintf(szCmdLine, “\\”%s\\” %d”, szFilename, nCloneID) ;
// 用于子进程的STARTUPINFO结构 STARTUPINFO si;
:: ZeroMemory(reinterpret_cast
// 返回的用于子进程的进程信息 PROCESS_INFORMATION pi;
// 利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质 BOOL bCreateOK = :: CreateProcess( szFilename, // 产生这个EXE的应用程序的名称 szCmdLine, // 告诉其行为像一个子进程的标志 NULL, // 缺省的进程安全性 NULL, // 缺省的线程安全性 FALSE, // 不继承句柄 CREATE_NEW_CONSOLE, // 使用新的控制台 NULL, // 新的环境 NULL, // 当前目录 &si, // 启动信息 &pi) ; // 返回的进程信息
// 对子进程释放引用 if (bCreateOK) {
:: CloseHandle(pi.hProcess) ; :: CloseHandle(pi.hThread) ; } }
int main(int argc, char* argv[] ) {
// 确定进程在列表中的位置 int nClone(0) ; if (argc > 1) {
// 从第二个参数中提取克隆ID :: sscanf(argv[1] , “%d” , &nClone) ; }
// 显示进程位置
std :: cout << “Process ID: “ << :: GetCurrentProcessId() << “, Clone ID: “ << nClone << std :: endl;
// 检查是否有创建子进程的需要 const int c_nCloneMax = 25; if (nClone < C_nCloneMax) {
// 发送新进程的命令行和克隆号 StartClone(++nClone) ; }
// 在终止之前暂停一下 (l/2秒) :: Sleep(500) ;
return 0; }
5