操作系统实验

更新时间:2019-12-23 10:28:58 点击次数:1728次
实验一:进程控制。
1、实验目的:通过在Windows 任务管理器中对进程进行相应的管理操作,熟悉操作系统进程管理的概念,学习观察操作系统运行的动态性能;学习创建进程、观察进程和终止进程的程序设计方法;理解Windows进程的“一生”。
2、实验内容:
(1) 使用任务管理器查看、终止进程;
(2) 创建进程;
(3) 获取进程运行信息,改变进程优先级;
(4) 终止进程。
3、实验步骤:
程序一:创建进程
(1) 父进程创建子进程,子进程创建下一个子进程;
(2) 创建子进程时将子进程序号作为命令行参数传给子进程,子进程将序号加一后继续创建下一个子进程;
(3) 限制创建子进程的最大个数;
(4) 进程在终止之前暂停一下,输入一个字符后,进程结束,以便观察。
思考题:

(1) 运行后在系统任务管理器中查看所创建进程映像名,有什么规律?

(2) 父子进程使用同一程序,具体是如何进行区别的?

(3) 不同进程的克隆ID是如何获取到的?

(4) 如果在克隆ID为0的进程中创建克隆ID为1-8的进程,应该如何修改程序?

程序二:查看进程运行信息
(1) 在main()函数中获取当前进程ID,获取当前进程版本信息;
(2) 获取操作系统版本信息;
(3) 获取当前进程优先级;
(4) 如果操作系统版本>=Windows XP,并且当前进程优先级不是HIGH_PRIORITY_CLASS,将当前进程优先级改为HIGH_PRIORITY_CLASS;
(5) 显示改变后的进程优先级。

思考题:
(1) 进程的优先级存放在哪里?

程序三:终止进程
(1) 在程序一的基础上,当前进程每创建一个新进程,增加一个参数,用以表示当前进程的进程ID;
(2) 新进程运行时获取父进程的进程ID;
(3) 在指定的进程中获取父进程的句柄;
(4) 在指定的进程中终止父进程。
思考题:
(1) 一个进程终止其父进程所需的句柄是如何获取的?
(2) Windows下的进程ID和进程句柄有什么区别?

// 实验一创建进程.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>

//创建子进程,与父进程执行相同的程序。
void StartClone(int nCloneID)
{

    // 获取当前进程的可执行文件名。
    TCHAR szFilename[MAX_PATH] ;
    :: GetModuleFileName(
          NULL, //一个模块的句柄。模块句柄跟一般的句柄不一样,
        //模块句柄指向的就是EXE和DLL等在内存的位置。
                        //如果该参数为NULL,该函数返回该应用程序全路径。
  szFilename,
  MAX_PATH) ;
   
    // 格式化用于创建新进程的命令行,包括EXE文件名和克隆ID
    TCHAR szCmdLine[MAX_PATH];
  :: sprintf(szCmdLine,"\"%s\"%d",szFilename,nCloneID);
  
// 用于新进程的STARTUPINFO结构
    STARTUPINFO si;
    :: ZeroMemory(reinterpret_cast <void*> (&si) , sizeof(si) ) ;
    si.cb = sizeof(si) ; // 必须是本结构的大小

    // 返回的用于新进程的进程信息
    PROCESS_INFORMATION pi;
    
    // 使用同一可执行文件和带有克隆ID的命令行创建新进程。
    BOOL bCreateOK=::CreateProcess(
        szFilename, // 新进程的可执行文件名
        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[] )
{
    // 进程的克隆ID
    int nClone(0) ;
    
    //第一个进程argc为1,以后每个进程命令行有两个参数,
    //其中第二个是克隆ID。
    if (argc > 1)
    {
        // 从第二个参数中提取克隆ID
        :: sscanf(argv[1] , "%d" , &nClone) ;
    }
    
    // 显示进程的克隆ID
    std :: cout << "Process ID:" << :: GetCurrentProcessId()
                << ", Clone ID:" << nClone
                << std :: endl;
    
    // 创建新进程,其nClone为1-8
    const int c_nCloneMax=8;
    if (nClone < c_nCloneMax)
    { 
        :: Sleep(3000) ;
        StartClone(++nClone) ;
    }
    
    // 在终止之前暂停一下。输入一个字符后,程序结束,以便观察。
    std::cout<<"input a char:";
    getchar();
    std::cout<<"I'm stopped ... Bye-Bye";
    :: Sleep(1000) ;
    return 0;
}

// 实验一终止进程.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>

//创建子进程,与父进程执行相同的程序。
void StartClone(int nCloneID)
{

    // 获取当前进程的可执行文件名取当前进程的可执行文件名
    TCHAR szFilename[MAX_PATH] ;
    :: GetModuleFileName(
          NULL, //一个模块的句柄。模块句柄跟一般的句柄不一样,
        //模块句柄指向的就是EXE和DLL等在内存的位置。
                        //如果该参数为NULL,该函数返回该应用程序全路径。
  szFilename,
  MAX_PATH) ;
   
    // 格式化用于创建新进程的命令行,包括EXE文件名、克隆ID和当前进程的ID。
    TCHAR szCmdLine[MAX_PATH];
:: sprintf(szCmdLine,"\"%s\"%d %d",szFilename,nCloneID,::GetCurrentProcessId());
  
// 用于新进程的STARTUPINFO结构
    STARTUPINFO si;
    :: ZeroMemory(reinterpret_cast <void*> (&si) , sizeof(si) ) ;
    si.cb = sizeof(si) ; // 必须是本结构的大小
    // 返回的用于新进程的进程信息
    PROCESS_INFORMATION pi;
    
    // 使用同一可执行文件和带有克隆ID、当前进程ID的命令行创建新进程。
    BOOL bCreateOK=::CreateProcess(
        szFilename, // 新进程的可执行文件名
        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[] )
{
    // 进程的克隆ID
    int nClone(0) ;
    // 保存父进程的进程ID
int ProcessId(0);
    
    //第一个进程argc为1,以后每个进程命令行有3个参数,
    //其中第3个是父进程ID。
    if (argc > 1)
    {
        // 从第2个参数中提取克隆ID
        :: sscanf(argv[1] , "%d" , &nClone) ;

// 从第3个参数中提取父进程ID
        :: sscanf(argv[2] , "%d" , &ProcessId) ;

    }
    
    // 显示进程ID和克隆ID
    std :: cout << "Process ID:" << :: GetCurrentProcessId()
                << ", Clone ID:" << nClone
                << std :: endl;

//终止父进程
if(nClone==3)
{
::TerminateProcess(OpenProcess(PROCESS_TERMINATE,FALSE,ProcessId),1);
std::cout<<"Terminate Process  Clone ID=2"
     << std :: endl;
}

    
    // 创建新进程,其nClone为1-8
    const int c_nCloneMax=8;
    if (nClone < c_nCloneMax)
    {
:: Sleep(2000) ;
        StartClone(++nClone) ;
    }
    
    // 在终止之前暂停一下。输入一个字符后,程序结束,以便观察。
    std::cout<<"input a char:";
    getchar();
    std::cout<<"I'm stopped ... Bye-Bye";
    :: Sleep(1000) ;
    return 0;
}

// 实验一查看进程运行信息.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>

// 进程和操作系统版本信息的简单示例
int main(int argc, char* argv[])
{
    // 获取这个进程的ID号
    DWORD dwIdThis=:: GetCurrentProcessId();
    
// 获得和显示这一进程所需的版本,也可以用0表示当前进程
    DWORD dwVerReq=:: GetProcessVersion(dwIdThis);
    WORD wMajorReq=(WORD)(dwVerReq>16) ;
    WORD wMinorReq=(WORD)(dwVerReq & 0xffff) ;
    std :: cout << "Process ID: "<< dwIdThis
                   <<", requires OS: " << wMajorReq <<"." 
                   << wMinorReq << std :: endl ;
    
// 设置版本信息的数据结构,以便保存操作系统的版本信息
    OSVERSIONINFOEX osvix;
    :: ZeroMemory(&osvix, sizeof(osvix) ) ;
    osvix.dwOSVersionInfoSize=sizeof(osvix) ;
   
// 获取版本信息和显示
    :: GetVersionEx(reinterpret_cast < LPOSVERSIONINFO > (&osvix)) ;
    std :: cout << "Running on OS:" << osvix.dwMajorVersion <<"."
                << osvix.dwMinorVersion << std :: endl;
    

//显示当前进程的优先级
//GetCurrentProcess()获得的句柄只是一个伪句柄,只能在我们的进程中才能代表当前进程的句柄,
//事实上这个函数目前只是简单的返回-1这个值。
DWORD dwProcessP=::GetPriorityClass(GetCurrentProcess());
  std::cout<<"Current process priority is :";
    switch(dwProcessP) 
{
            case HIGH_PRIORITY_CLASS:
     std::cout<<"High";
     break;
            case NORMAL_PRIORITY_CLASS:
     std::cout<<"Normal";
     break;
            case IDLE_PRIORITY_CLASS:
     std::cout<<"Idle";
      break;
            case REALTIME_PRIORITY_CLASS:
     std::cout<<"Realtime";
     break;
            default:
     std::cout<<"<unknow>";
     break;
}
    std::cout<<std::endl;
    
      // 如果是NTS(Windows 2000) 系统,则提高其优先权
      if (osvix.dwPlatformId==VER_PLATFORM_WIN32_NT && osvix.dwMajorVersion >= 5)
      {
        if(dwProcessP!=HIGH_PRIORITY_CLASS)
{
// 如果当前优先级不是high,则改变优先级为high
:: SetPriorityClass(
:: GetCurrentProcess() ,
HIGH_PRIORITY_CLASS);
    
//报告给用户
DWORD dwProcessP = GetPriorityClass(GetCurrentProcess());
std::cout<<"The Process priority have been changed to ";
switch(dwProcessP) 
{
case HIGH_PRIORITY_CLASS:
std::cout<<"High";
break;
case NORMAL_PRIORITY_CLASS:
std::cout<<"Normal";
break;
case IDLE_PRIORITY_CLASS:
std::cout<<"Idle";
      break;
case REALTIME_PRIORITY_CLASS:
std::cout<<"Realtime";
break;
default:
std::cout<<"<unknow>";
break;
}
std::cout<<std::endl;
}
}
return 0;
}

本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是一个个人学习交流的平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽,造成漏登,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

回到顶部
嘿,我来帮您!