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