编程中的进程管理.ppt

上传人:本田雅阁 文档编号:2258570 上传时间:2019-03-12 格式:PPT 页数:67 大小:490.51KB
返回 下载 相关 举报
编程中的进程管理.ppt_第1页
第1页 / 共67页
编程中的进程管理.ppt_第2页
第2页 / 共67页
编程中的进程管理.ppt_第3页
第3页 / 共67页
亲,该文档总共67页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《编程中的进程管理.ppt》由会员分享,可在线阅读,更多相关《编程中的进程管理.ppt(67页珍藏版)》请在三一文库上搜索。

1、,Windows系统编程实用教程,授课教师: 职务:,第7章 进程编程,课程描述 大多数应用程序都以进程的形式运行,有时还需要在应用程序里运行或结束其他进程。本章将介绍Windows进程编程的方法。,本章知识点,7.1 进程编程基础 7.2 基本进程编程 7.3 进程间通信,7.1 进程编程基础,7.1.1 什么是进程 7.1.2 进程的状态,7.1.1 什么是进程,进程是正在运行的程序的实例。每个运行的Visual C+项目都对应一个进程,每个进程至少包含一个线程,它从main()函数开始执行,直到执行return语句返回,主线程结束,该进程也被从内存中卸载。 进程由如下几个部分组成。 与程

2、序相关联的可执行代码的映像; 内存空间(通常是虚拟内存中的一些区域),其中保存可执行代码、进程的特定数据、用于记录活动例程和其他事件的调用栈、用于保存实时产生的中间计算结果的堆(heap)。 分配给进程的资源的操作系统描述符(比如文件句柄)以及其他数据资源。 安全属性,比如进程的所有者和权限。 处理器的状态,比如寄存器的内容、物理内存地址等。,7.1.2 进程的状态,7.2 基本进程编程,7.2.1 创建进程 7.2.2 枚举系统进程 7.2.3 终止进程,7.2.1 创建进程,在应用程序中可以调用CreateProcess()函数创建一个新进程、运行其他程序,函数原型如下: BOOL WIN

3、API CreateProcess( _in LPCTSTR lpApplicationName, _in_out LPTSTR lpCommandLine, _in LPSECURITY_ATTRIBUTES lpProcessAttributes, _in LPSECURITY_ATTRIBUTES lpThreadAttributes, _in BOOL bInheritHandles, _in DWORD dwCreationFlags, _in LPVOID lpEnvironment, _in LPCTSTR lpCurrentDirectory, _in LPSTARTUPINF

4、O lpStartupInfo, _out LPPROCESS_INFORMATION lpProcessInformation );,参数说明,lpApplicationName,要执行的应用程序名,可以包括结对路径和文件名,通常可以为NULL。 lpCommandLine,要执行的命令行。 lpProcessAttributes,新进程的安全描述符。 lpThreadAttributes,指定主线程的安全描述符。如果为NULL,则使用默认的安全描述符。 bInheritHandles,指示新进程是否从调用进程处继承句柄。 dwCreationFlags,指定附加的、用来控制优先类和进程创建

5、的标志。 lpEnvironment,指向新进程的环境块。如果为NULL,则使用调用CreateProcess()函数的进程的环境。,【例7.1】,调用CreateProcess()函数运行Windows计算器程序,并显示新进程的ID号,及其主线程的Id号,代码如下: #include “stdafx.h“ #include int _tmain(int argc, _TCHAR* argv) char szCommandLine=“calc.exe“; STARTUPINFO si = sizeof(si); PROCESS_INFORMATION pi; si.dwFlags = STAR

6、TF_USESHOWWINDOW; / 指定wShowWindow成员有效 si.wShowWindow = TRUE; / 显示新建进程的主窗口,接上,BOOL bRet = CreateProcess (NULL, / 不在此指定可执行文件的文件名 szCommandLine, / 命令行参数 NULL, / 默认进程安全性 NULL, / 默认进程安全性 FALSE, / 指定当前进程内句柄不可以被子进程继承 CREATE_NEW_CONSOLE, / 为新进程创建一个新的控制台窗口 NULL, / 使用本进程的环境变量 NULL, / 使用本进程的驱动器和目录 ,【例7.1】的运行结果

7、,ShellExecute()函数,HINSTANCE ShellExecute( HWND hwnd, / 指定显示用户界面和错误信息的窗口句柄 LPCTSTR lpOperation, / 对指定文件要执行的操作 LPCTSTR lpFile, / 要执行操作的文件或对象 LPCTSTR lpParameters, / 指定传送给应用程序的参数 LPCTSTR lpDirectory, / 指定执行操作的工作目录 INT nShowCmd / 指定应用程序如何显示。SW_HIDE表示隐藏窗口,SW_MAXIMIZE表示最大化窗口,SW_MINIMIZE表示最小化窗口,SW_SHOW表示在当

8、前位置上以当前大小显示窗口,等等 );,pOperation参数的取值,【例7.2】,【例7.2】调用ShellExecute ()函数访问google网站,代码如下: #include “stdafx.h“ #include “windows.h” int _tmain(int argc, _TCHAR* argv) ShellExecute(NULL, “open“, “http:/“, “ “, “ “, SW_SHOW); return 0; ,7.2.2 枚举系统进程,1使用EnumProcesses()函数 2使用进程快照,1使用EnumProcesses()函数,BOOL WIN

9、API EnumProcesses( _out DWORD* pProcessIds, / 用于接收进程标示符列表的数组 _in DWORD cb, / 数组pProcessIds的大小,单位是字节 _out DWORD* pBytesReturned/ 数组pProcessIds中返回数据的大小,单位是字节 ); 如果函数执行成功,则返回一个非0值;否则返回0。,【例7.3】,调用EnumProcess ()函数枚举当前Windows运行进程的标示符(PID),代码如下: #include “stdafx.h“ #include #include #pragma comment(lib, “

10、Psapi.lib“) int _tmain(int argc, _TCHAR* argv) / 用于接收返回的进程ID信息的数组 DWORD dwProcs1024*2; DWORD dwNeeded; /返回进程数组的大小 /枚举所有进程ID。,接上,if (!EnumProcesses( dwProcs, sizeof(dwProcs), ,【例7.3】的运行结果,2使用进程快照,HANDLE WINAPI CreateToolhelp32Snapshot( DWORD dwFlags, /指定快照中包含的对象 DWORD th32ProcessID / 指定获取进程快照的PID。如果为

11、0,则获取当前系统进程列表 ); 如果函数执行成功,则返回进程快照的句柄;否则返回INVALID_HANDLE_VALUE。,Process32First()函数,调用Process32First()函数可以从进程快照中获取第1个进程的信息,函数原型如下: BOOL WINAPI Process32First( HANDLE hSnapshot, / 之前调用createtoolhelp32napshot()函数得到的进程快照句柄 LPPROCESSENTRY32 lppe / 包含进程信息的结构体 );,结构体LPPROCESSENTRY32,LANA_ENUM结构体中包含当前逻辑网络适配器

12、的数量。当一个物理网络适配器绑定到一个网络协议时,就对应一个逻辑网络适配器。执行NCB命令NCBENUM可以向LANA_ENUM结构体中填充逻辑网络适配器的个数和逻辑网络适配器编号,此时NCB结构体中的ncb_buffer成员变量指向LANA_ENUM结构体。LANA_ENUM结构体的定义代码如下: typedef struct _LANA_ENUM UCHAR length; UCHAR lanaMAX_LANA; LANA_ENUM, *PLANA_ENUM; 参数说明如下: length,系统中包含的逻辑网络适配器数量。 lanaMAX_LANA,系统中包含的逻辑网络适配器编号数组。,P

13、rocess32Next()函数,调用Process32Next()函数可以从进程快照中获取下一个进程的信息,函数原型如下: BOOL WINAPI Process32Next( HANDLE hSnapshot, 、/ 之前调用createtoolhelp32napshot()函数得到的进程快照句柄 LPPROCESSENTRY32 lppe / 包含进程信息的结构体 ); 如果函数执行成功,则返回TRUE;否则返回FALSE。,【例7.4】,利用进程快照枚举当前Windows运行进程的信息,代码如下: #include “stdafx.h“ #include “windows.h“ #in

14、clude “tlhelp32.h“ int _tmain(int argc, _TCHAR* argv) PROCESSENTRY32 pe; /设置结构体pe的大小 pe.dwSize = sizeof(pe); /获取系统内进程的快照 HANDLE hProcessSnap = :CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if (hProcessSnap = INVALID_HANDLE_VALUE) printf(“CreateToolhelp32Snapshot error.n“); return -1; ,接上,/遍历进程快照,

15、显示每个进程的信息 BOOL bMore = :Process32First(hProcessSnap, ,4ASTAT结构体,ASTAT结构体用于描述网络适配器的状态和名字信息,定义代码如下: typedef struct ADAPTER_STATUS adapt; NAME_BUFFER NameBuff30; ASTAT; 参数adapt表示网络适配器的状态信息,参数NameBuff表示网络适配器中保存的本地网络名字信息。,【例7.4】的运行结果,7.2.3 终止进程,进程从主函数的第一行代码开始执行,直到主函数结束时终止;也可以强制结束一个进程。当进程被终止时,系统会进行下面的操作:

16、进程中的所有线程都被标记为“终止”状态; 分配给进程的所有资源都会被释放掉; 所有与该进程相关的内核对象都会被关闭; 从内存中移除该进程的代码; 系统设置进程的退出代码; 将该进程对象设置为“受信”(Sigaled)状态。,GetExitCodeProcess()函数,调用GetExitCodeProcess()函数可以获取进程的终止状态,函数原型如下: BOOL WINAPI GetExitCodeProcess( _in HANDLE hProcess, / 进程句柄 _out LPDWORD lpExitCode / 用于接收进程的终止状态 ); 如果函数执行成功,则返回TRUE;否则返

17、回FALSE。当进程在运行中时,其终止状态为STILL_ACTIVE。当进程被终止时,其终止状态变成退出代码。,ExitProcess()函数,在进程中调用ExitProcess()函数终止其自身中所有的线程,函数原型如下: VOID WINAPI ExitProcess( _in UINT uExitCode / 退出代码 );,TerminateProcess()函数,调用TerminateProcess()函数可以终止指定的进程,函数原型如下: BOOL WINAPI TerminateProcess( _in HANDLE hProcess, / 要终止的进程句柄 _in UINT u

18、ExitCode /退出代码 );,7.3 进程间通信,7.3.1 通过自定义消息进行通信 7.3.2 通过管道进行通信 7.3.3 使用互斥体 7.3.4 通过共享内存进行通信,7.3.1 通过自定义消息进行通信,1定义自定义消息的代码 2发送消息 3消息处理函数,1定义自定义消息的代码,为了唯一标识自定义消息,需要为其定义一个消息代码。自定义的消息代码都比WM_USER要大,因为0 WM_USER-1是保留给系统消息使用。可以使用下面的代码定义一个自定义消息WM_MY_MESSAGE: #define WM_MY_MESSAGE (WM_USER+100),2发送消息,调用PostMess

19、age()函数将消息放置到与创建指定窗口的进程相关联的消息队列中,函数不需要等待接收方接受和处理消息就直接返回。函数原型如下: BOOL PostMessage( HWND hWnd, / 接收消息的窗口句柄,使用HWND_BROADCAST表示所有顶层窗口 UINT Msg, / 发送消息的代码 WPARAM wParam, / 指定消息的附加信息 LPARAM lParam / 指定消息的附加信息 );,FindWindow()函数,HWND FindWindow( LPCTSTR lpClassName, /窗口类名,通常为NULL LPCTSTR lpWindowName / 要查找窗

20、口的标题 );,3消息处理函数,在接收端需要设计一个消息处理函数,它的格式如下: LRESULTOnMyMsg(WPARAM wParam, LPARAM lParam) / 处理代码 return 0; 参数wParam和lParam用于接收PostMessage()函数发送消息时指定的参数。,将消息与其处理函数映射起来,定义消息处理函数后还要将消息与其处理函数映射起来。在每个MFC对话框对应的.cpp文件中,都在BEGIN_MESSAGE_MAP宏和END_MESSAGE_MAP()宏之间定义消息与其处理函数映射的,例如: BEGIN_MESSAGE_MAP(CReceiverDlg, C

21、Dialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() /AFX_MSG_MAP END_MESSAGE_MAP(),BEGIN_MESSAGE_MAP宏,BEGIN_MESSAGE_MAP宏用于标识消息映射的开始,其原型如下: BEGIN_MESSAGE_MAP(theClass, baseClass ) 参数theClass指定消息映射所属的类,通常是窗口类;参数baseClass指定参数theClass的基类。在BEGIN_MESSAGE_MAP宏和END_MESSAGE_MAP()宏之间添加一条ON_MESSAGE宏

22、用于定义自定义消息及其处理函数的映射。ON_MESSAGE宏的原型如下: ON_MESSAGE(message, memberFxn ) 参数message用于指定自定义消息的代码,参数memberFxn指定消息处理函数。,【例7.5】,设计一个利用自定义消息实现进程间通信的例子。 1设计发送端项目 2设计接收端项目,1设计发送端项目,创建一个基于对话框的MFC应用程序Sender,定义自定义消息WM_MY_MESSAGE,代码如下: #define WM_MY_MESSAGE (WM_USER+999),单击“发送消息”按钮的代码,void CSenderDlg:OnBnClickedBut

23、tonSendmsg() HWND hWnd = :FindWindow(NULL, “Receiver“); :PostMessage(hWnd,WM_MY_MESSAGE, (WPARAM)999, NULL ); ,2设计接收端项目,创建一个基于对话框的MFC应用程序Receiver,定义自定义消息WM_MY_MESSAGE,代码如下: #define WM_MY_MESSAGE (WM_USER+999) 编写消息处理函数OnMyMsg(),代码如下: LRESULT CReceiverDlg:OnMyMsg(WPARAM wParam, LPARAM lParam) char msg

24、100; sprintf(msg, “%d“, (int)wParam); MessageBox(msg, “收到消息“); return 0; ,添加自定义消息及其处理函数的映射,BEGIN_MESSAGE_MAP(CReceiverDlg, CDialog) ON_MESSAGE(WM_MY_MESSAGE, OnMyMsg) / 映射消息和处理函数 /AFX_MSG_MAP END_MESSAGE_MAP(),7.3.2 通过管道进行通信,管道(Pipe)是由标准输入输出流构成的进程链。一个进程的输出直接作为下一个进程的输入。每个连接都是一个匿名管道。管道包含一个写句柄和一个读句柄。一个

25、进程使用写句柄向管道里写入数据,另一个进程使用读句柄从管道中读取数据。 调用CreatePipe()函数可以创建管道,函数原型如下: BOOL WINAPI CreatePipe( _out PHANDLE hReadPipe, / 管道的读句柄 _out PHANDLE hWritePipe, _in LPSECURITY_ATTRIBUTES lpPipeAttributes, _in DWORD nSize );,【例7.6】,设计一个利用管道实现进程间通信的例子。 主进程Server的代码如下: #include “stdafx.h“ #include int _tmain(int a

26、rgc, _TCHAR* argv) HANDLE hRead; / 管道读句柄 HANDLE hWrite; / 管道写句柄 SECURITY_ATTRIBUTES sa; / 设置管道属性 sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; / 指定管道句柄可以被子进程继承 BOOL bRet = CreatePipe(,接上,/ 得到本进程的当前标准输出,以备将来恢复 HANDLE hTemp = GetStdHandle(STD_OUTPU

27、T_HANDLE); / 设置标准输出到匿名管道 SetStdHandle(STD_OUTPUT_HANDLE, hWrite); STARTUPINFO si; GetStartupInfo(,接上,/ 读管道直至管道关闭 char ReadBuf100; DWORD ReadNum; / 循环从管道中读取数据 while (ReadFile(hRead, ReadBuf, 100, ,子进程Client的代码,#include “stdafx.h“ #include #include using namespace std; int _tmain(int argc, _TCHAR* arg

28、v) for (int i = 0; i 10; i+) / 发送一些数据到标准输出和标准错误 printf(“i = %d; “, i); / 打印提示 cout “标准输出:“ i endl; / 打印到标准输出 cerr “标准错误:“ i endl; / 打印到标准错误 return 0; ,【例7.6】的运行结果,7.3.3 使用互斥体,HANDLE WINAPI CreateMutex( _in LPSECURITY_ATTRIBUTES lpMutexAttributes, / 互斥体对象的安全属性,如果为NULLZ,则互斥体对象不能被子进程继承 _in BOOL bInitia

29、lOwner, / 初始化互斥对象的所有者 _in LPCTSTR lpName / 指定互斥对象的名字 ); 如果在不同进程间使用互斥体,则该互斥体对象是全局的。全局互斥体对象的名字必须以“Global”为前缀,而本地互斥体对象的名字则以“Local”为前缀。,【例7.7】,设计一个利用互斥体防止运行一个应用程序的多个实例的例子Mutex,代码如下: int _tmain(int argc, _TCHAR* argv) CreateMutex(NULL,TRUE, “GlobalMyMutex001“); if(GetLastError()=ERROR_ALREADY_EXISTS) pri

30、ntf(“应用程序已经运行!n“); exit(0); printf(“已进入应用程序.n“); system(“pause“); return 0; ,第1次运行Mutex.exe的结果,7.3.4 通过共享内存进行通信,每个Windows进程都有其私有的内存空间。任何进程都不能修改其他进程的内存空间,包括变量和对象等。但是多个进程间可以通过一块共享内存进行通信。共享内存是允许多个进程同时访问的内存,不同的进程可以通过共享内存进行通讯,也可以避免在不同的程序中保存多余的数据备份。通常可以使用内存映射文件实现共享内存,用内存映射文件是由一个文件到一块内存的映射。内存映射文件与虚拟内存有些类似,

31、通过内存映射文件可以保留一个地址空间的内存区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行过多的I/O操作,因此,内存映射文件在处理大数据量的文件时能起到相当重要的作用。,CreateFileMapping()函数,HANDLE CreateFileMapping( HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMax

32、imumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName );,参数说明,hFile:创建映射对象的文件句柄,如果使用INVALID_HANDLE_VALUE,则在物理内存中创建映射对象。 lpFileMappingAttributes:被忽略,必须为NULL。 flProtect,文件视图的保护方式。 dwMaximumSizeHigh,指定文件映射对象最大大小的高32位。 dwMaximumSizeLow,指定文件映射对象最大大小的低32位。 lpName,映射对象的名字,如果是全局映射对象,则名字可以以“Global”前缀开始。,MapVi

33、ewOfFile()函数,调用MapViewOfFile()函数可以将指定的文件视图映射到调用进程的地址空间,函数原型如下: LPVOID MapViewOfFile( HANDLE hFileMappingObject, /文件映射对象的句柄,通常由CreateFileMapping()函数返回 DWORD dwDesiredAccess, / 对文件视图的访问类型 DWORD dwFileOffsetHigh, / 指定开始映射的文件偏移量的高32位 DWORD dwFileOffsetLow, / 指定开始映射的文件偏移量的低32位 DWORD dwNumberOfBytesToMap

34、/ 指定文件映射的字节数。如果为0,则映射整个文件。 );,OpenFileMapping()函数,HANDLE WINAPI OpenFileMapping( _in DWORD dwDesiredAccess,/ 访问权限 _in BOOL bInheritHandle, / 指定子进程是否可以继承句柄 _in LPCTSTR lpName /指定要打开指定的文件映射对象的名字 ); 如果函数执行成功,则返回打开指定的文件映射对象句柄;否则返回NULL。可以调用GetLastError()函数获取错误代码。,UnmapViewOfFile()函数,调用UnmapViewOfFile()函数

35、可以从调用进程的地址空间中解除文件视图的映射。函数原型如下: BOOL UnmapViewOfFile( LPCVOID lpBaseAddress / 要解除的文件视图映射的基地址 );,【例7.8】,计一个创建文件映射对象,并向映射视图中写入数据的例子Process1,代码如下: #include “stdafx.h“ #include #include #include #define BUF_SIZE 256 / 共享内存的大小 TCHAR szName=TEXT(“GlobalMyFileMappingObject“); /文件映射对象的名字 TCHAR szMsg=TEXT(“Me

36、ssage from process1“); / 向共享内存中写入的数据 int _tmain(int argc, _TCHAR* argv) HANDLE hMapFile; LPCTSTR pBuf;,接上,/ 创建文件映射对象 hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, / 使用页文件 NULL, PAGE_READWRITE, / 可读写 0, BUF_SIZE, / 文件映射对象的大小 szName); / 文件映射对象的名字 if (hMapFile = NULL) printf(“Could not create fil

37、e mapping object (%d).n“, GetLastError(); return 1; ,接上,/ 将指定的文件视图映射到调用进程的地址空间,得到的pBuf地址就是共享内存的开始地址,共享内存的大小为BUF_SIZE pBuf = (LPTSTR) MapViewOfFile(hMapFile, / 映射对象的句柄 FILE_MAP_ALL_ACCESS, / 可读写 0, 0, BUF_SIZE); if (pBuf = NULL) printf(“Could not map view of file (%d).n“, GetLastError(); return 2; /

38、向共享内存中写入数据 CopyMemory(PVOID)pBuf, szMsg, strlen(szMsg); system(“pause“); / 等待其他进程从共享内存中读取数据 / 从调用进程的地址空间中解除文件视图的映射 UnmapViewOfFile(pBuf); / 关闭映射对象的句柄 CloseHandle(hMapFile); return 0; ,设计一个从Process1创建的映射视图中读取数据的例子Process2,#include “stdafx.h“ #include #include #include #define BUF_SIZE 256/ 共享内存的大小 TC

39、HAR szName=TEXT(“GlobalMyFileMappingObject“);/文件映射对象的名字 int _tmain(int argc, _TCHAR* argv) HANDLE hMapFile; LPCTSTR pBuf; / 打开例.8中创建的文件映射对象 hMapFile = OpenFileMapping( FILE_MAP_ALL_ACCESS, / 可读写 FALSE, / 指定子进程不继承句柄 szName); / 指定要打开指定的文件映射对象的名字,接上,if (hMapFile = NULL) printf(“Could not open file mapp

40、ing object (%d).n“, GetLastError(); system(“pause“); return 1; / 将指定的文件视图映射到调用进程的地址空间,得到的pBuf地址就是共享内存的开始地址,共享内存的大小为BUF_SIZE pBuf = (LPTSTR) MapViewOfFile(hMapFile, / 映射对象的句柄 FILE_MAP_ALL_ACCESS, /可读写 0, 0, BUF_SIZE);,接上,if (pBuf = NULL) printf(“Could not map view of file (%d).n“, GetLastError(); system(“pause“); return 2; / 打印共享内存中的数据 printf(“Read from Map file : %snn“, pBuf); / 从调用进程的地址空间中解除文件视图的映射 UnmapViewOfFile(pBuf); / 关闭映射对象的句柄 CloseHandle(hMapFile); system(“pause“); return 0; ,Process2的运行结果,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1