编程中的进程管理.ppt

上传人:sccc 文档编号:6001989 上传时间:2023-09-13 格式:PPT 页数:67 大小:490.54KB
返回 下载 相关 举报
编程中的进程管理.ppt_第1页
第1页 / 共67页
编程中的进程管理.ppt_第2页
第2页 / 共67页
编程中的进程管理.ppt_第3页
第3页 / 共67页
编程中的进程管理.ppt_第4页
第4页 / 共67页
编程中的进程管理.ppt_第5页
第5页 / 共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 WINAPI CreateProc

3、ess(_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 LPSTARTUPINFO lpStartupInfo,_out LP

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

5、为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=STARTF_USESHOWWINDOW;/指定wShowWindow成员有效si.wShowWind

6、ow=TRUE;/显示新建进程的主窗口,接上,BOOL bRet=CreateProcess(NULL,/不在此指定可执行文件的文件名szCommandLine,/命令行参数NULL,/默认进程安全性NULL,/默认进程安全性FALSE,/指定当前进程内句柄不可以被子进程继承CREATE_NEW_CONSOLE,/为新进程创建一个新的控制台窗口NULL,/使用本进程的环境变量NULL,/使用本进程的驱动器和目录,【例7.1】的运行结果,ShellExecute()函数,HINSTANCEShellExecute(HWNDhwnd,/指定显示用户界面和错误信息的窗口句柄LPCTSTRlpOper

7、ation,/对指定文件要执行的操作LPCTSTRlpFile,/要执行操作的文件或对象LPCTSTRlpParameters,/指定传送给应用程序的参数LPCTSTRlpDirectory,/指定执行操作的工作目录INTnShowCmd/指定应用程序如何显示。SW_HIDE表示隐藏窗口,SW_MAXIMIZE表示最大化窗口,SW_MINIMIZE表示最小化窗口,SW_SHOW表示在当前位置上以当前大小显示窗口,等等);,pOperation参数的取值,【例7.2】,【例7.2】调用ShellExecute()函数访问google网站,代码如下:#include stdafx.h#includ

8、e 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 WINAPI EnumProcesses(_out DWORD*pProcessIds,/用于接收进程标示符列表的数组 _in DWORD cb,/数组pProcessIds的大小,单位是字节 _out DWORD*pBytesReturned/数组pProcessIds中返回数

9、据的大小,单位是字节);如果函数执行成功,则返回一个非0值;否则返回0。,【例7.3】,调用EnumProcess()函数枚举当前Windows运行进程的标示符(PID),代码如下:#include stdafx.h#include#include#pragma comment(lib,Psapi.lib)int _tmain(int argc,_TCHAR*argv)/用于接收返回的进程ID信息的数组 DWORD dwProcs1024*2;DWORD dwNeeded;/返回进程数组的大小/枚举所有进程ID。,接上,if(!EnumProcesses(dwProcs,sizeof(dwPr

10、ocs),【例7.3】的运行结果,2使用进程快照,HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags,/指定快照中包含的对象 DWORD th32ProcessID/指定获取进程快照的PID。如果为0,则获取当前系统进程列表);如果函数执行成功,则返回进程快照的句柄;否则返回INVALID_HANDLE_VALUE。,Process32First()函数,调用Process32First()函数可以从进程快照中获取第1个进程的信息,函数原型如下:BOOL WINAPI Process32First(HANDLE hSnapshot,/之前调

11、用createtoolhelp32napshot()函数得到的进程快照句柄 LPPROCESSENTRY32 lppe/包含进程信息的结构体);,结构体LPPROCESSENTRY32,LANA_ENUM结构体中包含当前逻辑网络适配器的数量。当一个物理网络适配器绑定到一个网络协议时,就对应一个逻辑网络适配器。执行NCB命令NCBENUM可以向LANA_ENUM结构体中填充逻辑网络适配器的个数和逻辑网络适配器编号,此时NCB结构体中的ncb_buffer成员变量指向LANA_ENUM结构体。LANA_ENUM结构体的定义代码如下:typedef struct _LANA_ENUM UCHAR l

12、ength;UCHAR lanaMAX_LANA;LANA_ENUM,*PLANA_ENUM;参数说明如下:length,系统中包含的逻辑网络适配器数量。lanaMAX_LANA,系统中包含的逻辑网络适配器编号数组。,Process32Next()函数,调用Process32Next()函数可以从进程快照中获取下一个进程的信息,函数原型如下:BOOL WINAPI Process32Next(HANDLE hSnapshot,、/之前调用createtoolhelp32napshot()函数得到的进程快照句柄 LPPROCESSENTRY32 lppe/包含进程信息的结构体);如果函数执行成功

13、,则返回TRUE;否则返回FALSE。,【例7.4】,利用进程快照枚举当前Windows运行进程的信息,代码如下:#include stdafx.h#include windows.h#include tlhelp32.hint _tmain(int argc,_TCHAR*argv)PROCESSENTRY32 pe;/设置结构体pe的大小pe.dwSize=sizeof(pe);/获取系统内进程的快照HANDLE hProcessSnap=:CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);if(hProcessSnap=INVALID_HAND

14、LE_VALUE)printf(CreateToolhelp32Snapshot error.n);return-1;,接上,/遍历进程快照,显示每个进程的信息BOOL bMore=:Process32First(hProcessSnap,4ASTAT结构体,ASTAT结构体用于描述网络适配器的状态和名字信息,定义代码如下:typedef struct ADAPTER_STATUS adapt;NAME_BUFFER NameBuff30;ASTAT;参数adapt表示网络适配器的状态信息,参数NameBuff表示网络适配器中保存的本地网络名字信息。,【例7.4】的运行结果,7.2.3 终止进

15、程,进程从主函数的第一行代码开始执行,直到主函数结束时终止;也可以强制结束一个进程。当进程被终止时,系统会进行下面的操作:进程中的所有线程都被标记为“终止”状态;分配给进程的所有资源都会被释放掉;所有与该进程相关的内核对象都会被关闭;从内存中移除该进程的代码;系统设置进程的退出代码;将该进程对象设置为“受信”(Sigaled)状态。,GetExitCodeProcess()函数,调用GetExitCodeProcess()函数可以获取进程的终止状态,函数原型如下:BOOL WINAPI GetExitCodeProcess(_inHANDLE hProcess,/进程句柄 _outLPDWOR

16、D lpExitCode/用于接收进程的终止状态);如果函数执行成功,则返回TRUE;否则返回FALSE。当进程在运行中时,其终止状态为STILL_ACTIVE。当进程被终止时,其终止状态变成退出代码。,ExitProcess()函数,在进程中调用ExitProcess()函数终止其自身中所有的线程,函数原型如下:VOID WINAPI ExitProcess(_inUINT uExitCode/退出代码);,TerminateProcess()函数,调用TerminateProcess()函数可以终止指定的进程,函数原型如下:BOOL WINAPI TerminateProcess(_inH

17、ANDLE hProcess,/要终止的进程句柄 _inUINT uExitCode/退出代码);,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_U

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

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

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

21、息及其处理函数的映射。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:OnBnClickedButtonSendmsg()HWND

22、 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 msg100;sprintf(msg,%d,(int)wParam);M

23、essageBox(msg,收到消息);return 0;,添加自定义消息及其处理函数的映射,BEGIN_MESSAGE_MAP(CReceiverDlg,CDialog)ON_MESSAGE(WM_MY_MESSAGE,OnMyMsg)/映射消息和处理函数/AFX_MSG_MAPEND_MESSAGE_MAP(),7.3.2 通过管道进行通信,管道(Pipe)是由标准输入输出流构成的进程链。一个进程的输出直接作为下一个进程的输入。每个连接都是一个匿名管道。管道包含一个写句柄和一个读句柄。一个进程使用写句柄向管道里写入数据,另一个进程使用读句柄从管道中读取数据。调用CreatePipe()函数

24、可以创建管道,函数原型如下: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 argc,_TCHAR*argv)HANDLE hRead;/管道读句柄HANDLE hWrite;/管道写句柄SECURITY_

25、ATTRIBUTES sa;/设置管道属性sa.nLength=sizeof(SECURITY_ATTRIBUTES);sa.lpSecurityDescriptor=NULL;sa.bInheritHandle=TRUE;/指定管道句柄可以被子进程继承BOOL bRet=CreatePipe(,接上,/得到本进程的当前标准输出,以备将来恢复HANDLE hTemp=GetStdHandle(STD_OUTPUT_HANDLE);/设置标准输出到匿名管道SetStdHandle(STD_OUTPUT_HANDLE,hWrite);STARTUPINFO si;GetStartupInfo(,接

26、上,/读管道直至管道关闭char ReadBuf100;DWORD ReadNum;/循环从管道中读取数据while(ReadFile(hRead,ReadBuf,100,子进程Client的代码,#include stdafx.h#include#include using namespace std;int _tmain(int argc,_TCHAR*argv)for(int i=0;i 10;i+)/发送一些数据到标准输出和标准错误printf(i=%d;,i);/打印提示cout 标准输出:i endl;/打印到标准输出cerr 标准错误:i endl;/打印到标准错误return

27、0;,【例7.6】的运行结果,7.3.3 使用互斥体,HANDLE WINAPI CreateMutex(_in LPSECURITY_ATTRIBUTES lpMutexAttributes,/互斥体对象的安全属性,如果为NULLZ,则互斥体对象不能被子进程继承 _in BOOL bInitialOwner,/初始化互斥对象的所有者 _in LPCTSTR lpName/指定互斥对象的名字);如果在不同进程间使用互斥体,则该互斥体对象是全局的。全局互斥体对象的名字必须以“Global”为前缀,而本地互斥体对象的名字则以“Local”为前缀。,【例7.7】,设计一个利用互斥体防止运行一个应用程

28、序的多个实例的例子Mutex,代码如下:int _tmain(int argc,_TCHAR*argv)CreateMutex(NULL,TRUE,GlobalMyMutex001);if(GetLastError()=ERROR_ALREADY_EXISTS)printf(应用程序已经运行!n);exit(0);printf(已进入应用程序.n);system(pause);return 0;,第1次运行Mutex.exe的结果,7.3.4 通过共享内存进行通信,每个Windows进程都有其私有的内存空间。任何进程都不能修改其他进程的内存空间,包括变量和对象等。但是多个进程间可以通过一块共享

29、内存进行通信。共享内存是允许多个进程同时访问的内存,不同的进程可以通过共享内存进行通讯,也可以避免在不同的程序中保存多余的数据备份。通常可以使用内存映射文件实现共享内存,用内存映射文件是由一个文件到一块内存的映射。内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的内存区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而且在对该文件进行操作之前必须首先对文件进行映射。使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行过多的I/O操作,因此,内存映射文件在处理大数据量的文件时能起到相当重要的作用。,CreateFileMapp

30、ing()函数,HANDLE CreateFileMapping(HANDLE hFile,LPSECURITY_ATTRIBUTES lpFileMappingAttributes,DWORD flProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,LPCTSTR lpName);,参数说明,hFile:创建映射对象的文件句柄,如果使用INVALID_HANDLE_VALUE,则在物理内存中创建映射对象。lpFileMappingAttributes:被忽略,必须为NULL。flProtect,文件视图的保护方式。dwMaximumS

31、izeHigh,指定文件映射对象最大大小的高32位。dwMaximumSizeLow,指定文件映射对象最大大小的低32位。lpName,映射对象的名字,如果是全局映射对象,则名字可以以“Global”前缀开始。,MapViewOfFile()函数,调用MapViewOfFile()函数可以将指定的文件视图映射到调用进程的地址空间,函数原型如下:LPVOID MapViewOfFile(HANDLE hFileMappingObject,/文件映射对象的句柄,通常由CreateFileMapping()函数返回 DWORD dwDesiredAccess,/对文件视图的访问类型 DWORD dw

32、FileOffsetHigh,/指定开始映射的文件偏移量的高32位 DWORD dwFileOffsetLow,/指定开始映射的文件偏移量的低32位 DWORD dwNumberOfBytesToMap/指定文件映射的字节数。如果为0,则映射整个文件。);,OpenFileMapping()函数,HANDLE WINAPI OpenFileMapping(_in DWORD dwDesiredAccess,/访问权限 _in BOOL bInheritHandle,/指定子进程是否可以继承句柄 _in LPCTSTR lpName/指定要打开指定的文件映射对象的名字);如果函数执行成功,则返回

33、打开指定的文件映射对象句柄;否则返回NULL。可以调用GetLastError()函数获取错误代码。,UnmapViewOfFile()函数,调用UnmapViewOfFile()函数可以从调用进程的地址空间中解除文件视图的映射。函数原型如下:BOOL UnmapViewOfFile(LPCVOID lpBaseAddress/要解除的文件视图映射的基地址);,【例7.8】,计一个创建文件映射对象,并向映射视图中写入数据的例子Process1,代码如下:#include stdafx.h#include#include#include#define BUF_SIZE 256/共享内存的大小TC

34、HAR szName=TEXT(GlobalMyFileMappingObject);/文件映射对象的名字TCHAR szMsg=TEXT(Message from process1);/向共享内存中写入的数据int _tmain(int argc,_TCHAR*argv)HANDLE hMapFile;LPCTSTR pBuf;,接上,/创建文件映射对象 hMapFile=CreateFileMapping(INVALID_HANDLE_VALUE,/使用页文件 NULL,PAGE_READWRITE,/可读写 0,BUF_SIZE,/文件映射对象的大小 szName);/文件映射对象的名字

35、 if(hMapFile=NULL)printf(Could not create file 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,GetLast

36、Error();return 2;/向共享内存中写入数据 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/共享内存的大小TCHAR

37、 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 mapping object(%d).n,GetLastEr

38、ror();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备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号