. .
华北电力大学
实 验 报 告
| |
实验名称
验证性试验、设计性试验
体系及编程
课程名称 Windows
| |
专业班级: 计科0803 学生:董世令
学 号:2 成 绩:
指导教师:王新颖 实验日期:2011.4.8
进程管理实验
一、实验目的
理解Windows编程环境下的进程管理机制,能创建一个完成特定功能的进程,并能对进程进行信息的获取、终止和保护。
. . .
. .
二、实验要求
1. 编写一段程序,能够完成创建进程的功能,要求启动windows记事本程序
(notepad.exe),同时打开一个文本文件,路径为:c:\\system\%user.log 。并打印出新建进程ID。
2. 获取当前系统进程信息,打印输出进程名称和ID号。 3. 终止新创建的进程并获取退出代码。 三、实验原理
(1)进程的创建
进程的创建通过CreateProcess()函数来实现,CreateProcess()通过创建一个新的进程及在其地址空间运行的主线程来启动并运行一个新的程序。具体地,在执行
CreateProcess()函数时,首先由操作系统负责创建一个进程核对象,初始化计数为1,并立即为新进程创建一块虚拟地址空间。随后将可执行文件或其他任何必要的动态库文件的代码和数据装载到该地址空间中。在创建主线程时,也是首先由系统负责创建一个线程核对象,并初始化为1。最后启动主线程并执行进程的入口函数WinMain(),完成对进程和执行线程的创建。
CreateProcess()函数的原型声明如下: BOOL CreateProcess(
LPCTSTR lpApplicationName, // 可执行模块名 LPTSTR lpCommandLine, // 命令行字符串 LPSECURITY_ATTRIBUTES lpProcessAttributes, // 进程的安全属性 LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程的安全属性 BOOL bInheritHandles, // 句柄继承标志 DWORD dwCreationFlags, // 创建标志
LPVOID lpEnvironment, // 指向新的环境块的指针 LPCTSTR lpCurrentDirectory, // 指向当前目录名的指针 LPSTARTUPINFO lpStartupInfo, // 指向启动信息结构的指针 LPPROCESS_INFORMATION lpProcessInformation // 指向进程信息结构的指针 );
(2)进程的获取
进程的定义是为执行程序指令的线程而保留的一系列资源的集合。进程是一个可执行的程序,由私有虚拟地址空间、代码、数据和其他操作系统资源(如进程创建的文件、管道、同步对象等)组成。进程是一些所有权的集合,一个进程拥有存、CPU运行时间等一系列资源,为线程的运行提供一个环境,每个进程都有它自己的地址空间和动态分配的存、线程、文件和其他一些模块。
系统快照的获取可以通过Win32 API函数CreateToolhelp32Snapshot()来完成,通过该函数不仅可以获取进程的快照,同样可以获取堆、模块和线程的系统快照。函数的声明如下:
HANDLE WINAPI CreateToolhelp32Snapshot(
. . .
. .
DWORD dwFlags, //指定要创建包含哪一类系统信息的快照函数 DWORD th32ProcessID //指定进程的ID号,当设定为0时表示指定当前进程
);
一旦系统得到系统快照句柄,就可以对当前的标识号进行枚举,进程号通过函数Process32First()和Procee32Next()得到,这两个函数可以用于获取系统快照中第一个和下一个系统的信息,这两个函数的声明如下:
BOOL WINAPI Process32First(
HANDLE hSnapshot, // 系统快照句柄
LPPROCESSENTRY32 lppe // 指向结构体PROCESSENTRY32的指针 );
BOOL WINAPI Process32Next(
HANDLE hSnapshot, // 系统快照句柄
LPPROCESSENTRY32 lppe // 指向结构体PROCESSENTRY32的指针 );
(3)进程的终止
终止进程也就是结束进程,让进程从存中卸载。进程的终止的原因一般有4种。 1) 主线程的入口函数返回。
2) 进程中的一个线程调用ExitProcess函数。 3) 次进程中的所有线程结束。 4) 其他进程中又有线程都结束。
要结束当前进程一般让主线程的入口函数返回。当用户的程序入口函数返回的时候,启动函数会调用C/C++运行期退出函数EXIT,并将用户的返回值传递给它。EXTI函数会销毁所有全局的或静态的C++对象,然后调用系统函数ExitProcess促使操作系统终止应用程序。ExitProcess是一个API函数,它会结束当前应用程序的执行,并设置退出代码,函数声明如下:
Void ExitProcess(UINT uExitCode); //参数uExitCode为此程序的退出代码
四、实验所需仪器、设备、材料(试剂)
Windows操作系统,Microsoft Visual c++6.0或.NET环境,msdn帮助文档。 五、实验正文 #include \#include
#include
BOOL bRet = FALSE;
// 打开目标进程,取得进程句柄
. . .
. .
HANDLE hProcess = ::OpenProcess (PROCESS_ALL_ACCESS, FALSE, dwId); //PROCESS_ALL_ACCESS:所有权限,包括创建、读、写等。 //OpenProcess如果成功,则该进程核对象引用计数+1 if(hProcess != NULL) {
bRet = ::TerminateProcess(hProcess, 0);
CloseHandle(hProcess);//结束了进程,还要使该进程核对象引用计数-1 }
return bRet; }
int main(int argc, char* argv[]) {
char szCommandLine[] = \ STARTUPINFO si = { sizeof(si) }; PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESHOWWINDOW; // 指定wShowWindow成员有效
si.wShowWindow = TRUE; // 此成员设为TRUE的话则显示新建进程的主窗口,
// 为FALSE的话则不显示 BOOL bRet = ::CreateProcess (
NULL, // 不在此指定可执行文件的文件名 szCommandLine, // 命令行参数 NULL, // 默认进程安全性 NULL, // 默认线程安全性
FALSE, // 指定当前进程的句柄不可以被子进程继承 CREATE_NEW_CONSOLE, // 为新进程创建一个新的控制台窗口 NULL, // 使用本进程的环境变量 NULL, // 使用本进程的驱动器和目录 &si, &pi);
if(bRet) {
// 既然我们不使用两个句柄,最好是立刻将它们关闭 ::CloseHandle (pi.hThread); ::CloseHandle (pi.hProcess);
printf(\新进程的进程ID号:%d \\n\
printf(\新进程的主线程ID号:%d \\n\ }
PROCESSENTRY32 pe32; // 在使用这个结构之前,先设置它的大小
. . .
. .
pe32.dwSize = sizeof(pe32); // 给系统的所有进程拍一个快照
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hProcessSnap == INVALID_HANDLE_VALUE)
{ printf(\调用失败! \\n\ return -1; }
BOOL bMore = ::Process32First(hProcessSnap, &pe32);// 遍历快照,轮流显示每个进程的信息
while(bMore)
{ printf(\进程名称:%s \\n\
printf(\进程ID号:%u \\n\\n\ bMore = ::Process32Next(hProcessSnap, &pe32); }
// 不要忘记清除掉snapshot对象 ::CloseHandle(hProcessSnap);
DWORD dwId;
printf(\请输入您要终止的进程的ID号: \\n\ scanf(\
if(TerminateProcessFromId(dwId)) {
printf(\终止进程成功! \\n\ } else {
printf(\终止进程失败! \\n\ }
return 0; }
运行结果:
. . .