[转]PROCESS_INFOMATION

typedef struct _PROCESS_INFORMATION {
  HANDLE hProcess; // 存放每个对象的与进程相关的句柄
  HANDLE hThread; // 返回的线程句柄
  DWORD dwProcessId; // 用来存放进程ID号
  DWORD dwThreadId; // 用来存放线程ID号
} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION;

  调用Createprocess()函数后,会自动地对该结构进行填充。

  创建新进程可使系统建立一个进程内核对象和一个线程内核对象。在创建进程的时候,系统为每个对象赋予一个初始使用计数值1 。然后,在createProcess返回之前,该函数打开进程对象和线程对象,并将每个对象的与进程相关的句柄放入PROCESS_INFORMATION结构的hProcess和hThread成员中。当CreateProcess在内部打开这些对象时,每个对象的使用计数就变为2。

  这意味着在系统能够释放进程对象前,该进程必须终止运行(将使用计数递减为1),并且父进程必须调用CloseHandle(再将使用计数递减1,使之变为0)。同样,若要释放线程对象,该线程必须终止运行,父进程必须关闭线程对象的句柄。

  注意,必须关闭子进程和它的主线程的句柄,以避免在应用程序运行时泄漏资源。当然,当进程终止运行时,系统会自动消除这些泄漏现象。但是,当进程不再需要访问子进程和它的线程时,编写得较好的软件能够显式关闭这些句柄(通过调用CloseHandle 函数来关闭)。不能关闭这些句柄是开发人员最常犯的错误之一。

  由于某些原因,许多开发人员认为,关闭进程或线程的句柄,会促使系统撤消该进程或线程。实际情况并非如此。关闭句柄只是告诉系统,你对进程或线程的统计数据不感兴趣。进程或线程将继续运行,直到它自己终止运行。

  当进程内核对象创建后,系统赋予该对象一个独一无二的标识号,系统中的其他任何进程内核对象都不能使用这个相同的ID号。线程内核对象的情况也一样。当一个线程内核对象创建时,该对象被赋予一个独一无二的、系统范围的ID号。进程ID和线程ID共享相同的号码池。这意味着进程和线程不可能拥有相同的ID。另外,对象绝不会被赋予0作为其ID。在CreateProcess返回之前,它要用这些ID填入PROCESS_INFORMATION结构的dwProcessId和dwThreadId成员中。ID使你能够非常容易地识别系统中的进程和线程。一些实用工具(如Task Manager)对ID使用得最多,而高效率的应用程序则使用得很少。由于这个原因,大多数应用程序完全忽略ID。

  如果应用程序使用ID来跟踪进程和线程,必须懂得系统会立即复用进程ID和线程ID。例如,当一个进程被创建时,系统为它指定一个进程对象,并为它赋予ID值122。如果创建了一个新进程对象,系统不会将相同的ID赋予给它。但是,如果第一个进程对象被释放,系统就可以将122赋予创建的下一个进程对象。记住这一点后,就能避免编写引用不正确的进程对象或线程对象的代码。获取进程ID是很容易的,保存该ID也不难,但是,接下来你应该知道,该ID标识的进程已被释放,新进程被创建并被赋予相同的ID。当使用已经保存的进程ID时,最终操作的是新进程,而不是原先获得ID的进程。

  有时,运行的应用程序想要确定它的父进程。首先应该知道只有在生成子进程时,才存在进程之间的父子关系。在子进程开始执行代码前,Windows不再考虑存在什么父子关系。较早的Windows 版本没有提供让进程查询其父进程的函数。现在,ToolHelp函数通过PROCESSENTRY32结构使得这种查询成为可能。在这个结构中有一个th32ParentProcess ID成员,根据文档的说明,它能返回进程的父进程的ID。

  系统无法记住每个进程的父进程的ID,但是,由于ID是被立即重复使用的,因此,等到获得父进程的ID时,该ID可能标识了系统中一个完全不同的进程。父进程可能已经终止运行。如果应用程序想要与它的“创建者”进行通信,最好不要使用ID。应该定义一个持久性更好的机制,比如内核对象和窗口句柄等。

  若要确保进程ID或线程ID不被重复使用,唯一的方法是保证进程或线程的内核对象不会被撤消。如果刚刚创建了一个新进程或线程,只要不关闭这些对象的句柄,就能够保证进程对象不被撤消。一旦应用程序结束使用该ID,那么调用CloseHandle就可以释放内核对象,要记住,这时使用或依赖进程ID,对父进程来说将不再安全。如果使用的是子进程,将无法保证父进程或父线程的有效性,除非父进程复制了它自己的进程对象或线程对象的句柄,并让子进程继承这些句柄。

转载自:http://blog.csdn.net/akof1314/archive/2010/04/11/5471768.aspx

原文地址:https://www.cnblogs.com/arsblog/p/4560330.html