zoukankan      html  css  js  c++  java
  • Windows程序设计(1)——Win32运行原理(三)

    4 进程控制

    4.1 获得系统进程

    使用toolhelp模块可以实现获取系统中当前运行当中的进程列表。

    思路如下,使用CreateToolhelp32Snapshot函数给当前系统内执行的进程拍快照(Snapshot),也就是获得了进程列表,这个列表记录着进程的ID、进程对应的可执行文件的名称和创建该进程的进程ID等数据。然后使用Process32First函数和Process32Next函数遍历快照中记录的列表。

    #include <windows.h>
    #include <TlHelp32.h> // for snapshot
    #include <stdio.h>
    
    int main(int argc, char* argv[])
    {
        PROCESSENTRY32 pe32;
        int iProcessCount;
    
        // initial its size
        pe32.dwSize = sizeof(pe32);
        iProcessCount = 0;
    
        // create snapshot for all processes
        HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (hProcessSnap == INVALID_HANDLE_VALUE)
        {
            printf("CreateToolhelp32Snapshot failure!
    ");
            exit(1);
        }
    
        // traversal snapshot
        BOOL bMore = ::Process32First(hProcessSnap, &pe32);
        while (bMore) 
        {
            printf("%-20.20s%6u%4u%6u%6u%6u%3ld
    ", pe32.szExeFile, 
                pe32.th32ProcessID, pe32.cntUsage, pe32.th32DefaultHeapID, 
                pe32.th32ModuleID, pe32.th32ParentProcessID, pe32.pcPriClassBase);
            bMore = ::Process32Next(hProcessSnap, &pe32);
            iProcessCount ++;
        }
    
        // clear snapshot
        ::CloseHandle(hProcessSnap);
    
        printf("Processes count: %d
    
    ", iProcessCount);
    
        getchar();
        return 0;
    }

    结果很容易理解。

    CreateToolhelp32Snapshot

    CreateToolhelp32Snapshot用于获取系统内指定进程的快照,也可以获取这些进程使用的堆、模块、线程的快照。如:

    HANDLE WINAPI CreateToolhelp32Snapshot( 
        DWORD dwFlags,      // 指定快照内容
        DWORD th32ProcessID // 指定进程ID
    );

    dwFlags参数可以是如下值:

    • TH32CS_SNAPHEAPLIST枚举`th32ProcessID参数指定进程中的堆。
    • TH32CS_SNAPMODULE枚举`th32ProcessID参数指定进程中的模块。
    • TH32CS_SNAPPROCESS,此时`th32ProcessID参数被忽略。
    • TH32CS_SNAPTHREAD,此时`th32ProcessID参数被忽略。
    • TH32CS_SNAPALL,相当于以上4个值的并集。

    根据获取快照的不同,使用下面几组函数来获取快照信息:

    • Heap32ListFirst Heap32ListNext
    • Module32First Module32Next
    • Process32First Process32Next
    • Thread32First Thread32Next
    • Heap32First Heap32Next

    以上函数的第二个参数是指向如下之一结构的指针:

    • HEAPLIST32
    • HEAPENTRY32
    • MODULEENTRY32
    • THREADENTRY32
    • PROCESSENTRY32
    typedef struct tagHEAPLIST32 { 
        DWORD dwSize; 
        DWORD th32ProcessID; 
        DWORD th32HeapID; 
        DWORD dwFlags; 
    } HEAPLIST32; 
    
    typedef struct tagHEAPENTRY32 
    { 
        DWORD dwSize; 
        HANDLE hHandle; 
        DWORD dwAddress; 
        DWORD dwBlockSize; 
        DWORD dwFlags; 
        DWORD dwLockCount; 
        DWORD dwResvd; 
        DWORD th32ProcessID; 
        DWORD th32HeapID; 
    } HEAPENTRY32;
    
    typedef struct tagMODULEENTRY32 { 
        DWORD dwSize; 
        DWORD th32ModuleID; 
        DWORD th32ProcessID; 
        DWORD GlblcntUsage; 
        DWORD ProccntUsage; 
        BYTE *modBaseAddr; 
        DWORD modBaseSize; 
        HMODULE hModule;
        TCHAR szModule[MAX_MODULE_NAME32 + 1]; 
        TCHAR szExePath[MAX_PATH]; 
        DWORD dwFlags
    } MODULEENTRY32;
    
    typedef struct tagTHREADENTRY32{ 
        DWORD dwSize; 
        DWORD cntUsage; 
        DWORD th32ThreadID; 
        DWORD th32OwnerProcessID; 
        LONG tpBasePri; 
        LONG tpDeltaPri; 
        DWORD dwFlags;
        DWORD th32AccessKey;
        DWORD th32CurrentProcessID;
    } THREADENTRY32; 
    
    typedef struct tagPROCESSENTRY32 { 
        DWORD dwSize; 
        DWORD cntUsage; 
        DWORD th32ProcessID; 
        DWORD th32DefaultHeapID; 
        DWORD th32ModuleID; 
        DWORD cntThreads; 
        DWORD th32ParentProcessID; 
        LONG pcPriClassBase; 
        DWORD dwFlags; 
        TCHAR szExeFile[MAX_PATH]; 
        DWORD th32MemoryBase;
        DWORD th32AccessKey;
    } PROCESSENTRY32; 
    

    4.2 终止当前进程

    终止一个进程有如下4种方式:

    1. 主线程的入口函数返回。
    2. 进程中一个线程调用了ExitProcess函数。
    3. 此进程中的所有线程都结束了。
    4. 其他进程中的一个线程调用了TerminateProcess函数。

    最常用的方式是让主线程的入口函数返回。当入口函数返回时,启动函数会调用C/C++运行期退出函数exit,并将用户的返回值传递给它。exit函数会销毁所有的全局的或者静态的C++对象,然后调用系统函数ExitProcess使操作系统终止应用程序。ExitProcess是一个API函数,它会结束当前应用程序的执行,并设置它的退出代码。

    VOID ExitProcess(  
        UINT uExitCode   // 所有线程的退出代码
    );

    在程序的任何地方都可以调用ExitProcess,强制当前程序的执行立即结束。这对操作系统来说,是正常的。但对C/C++应用程序应该避免直接调用这个函数。因为这会使C/C++运行期库得不到通知,而没有机会去调用全局的或者静态的C++对象的析构函数。

    4.3 终止其他进程

    ExitProcess函数只能用来结束当前进程,不能用于结束其他进程。如果要终止其他进程,可以使用TerminateProcess函数。

    BOOL TerminateProcess(
        HANDLE hProcess, // 目标进程句柄
        UINT uExitCode   // 目标进程的退出代码
    );

    前面介绍过,使用CreateProcess函数创建新的进程,会得到新进程的句柄。对于不是自己创建的进程,可以使用OpenProcess函数来取得这进程的访问权限,函数如下:

    HANDLE OpenProcess(
        DWORD dwDesiredAccess,  // 访问权限
        BOOL bInheritHandle,    // 返回的句柄是否可被继承
        DWORD dwProcessId       // 要打开的进程的ID
    );

    参数dwDesiredAccess指定的对进程的访问权限,可以是如下值:

    说明
    PROCESS_ALL_ACCESS 所有可进行的权限
    PROCESS_CREATE_PROCESS 创建一个进程
    PROCESS_CREATE_THREAD 创建一个线程
    PROCESS_DUP_HANDLE 做为DuplicateHandle参数
    PROCESS_QUERY_INFORMATION 查看进程信息的权限,如优先级类等
    PROCESS_QUERY_LIMITED_INFORMATION 需要返回特定信息
    PROCESS_SET_INFORMATION 设置进程的优先级
    PROCESS_SET_QUOTA 设置内存限制
    PROCESS_SUSPEND_RESUME 睡眠和唤醒
    PROCESS_TERMINATE 关闭进程
    PROCESS_VM_OPERATION 修改进程的地址空间
    PROCESS_VM_READ 读进程内存
    PROCESS_VM_WRITE 写进程内存
    SYNCHRONIZE 等待进程结束

    在进程结束后,调用GetExitCodeProcess函数可以取得其退出代码,如果调用时,目标进程还没有结束,此函数会返回STILL_ACTIVE,表示进程还在运行。通过该函数可以检测进程是否结束了。

    BOOL GetExitCodeProcess(
        HANDLE hProcess,     // 目标进程句柄
        LPDWORD lpExitCode   // 目标进程的退出句柄
    );

    如果进程已经结束,其退出代码是通过下面几种方式设置的:

    1. ExitProcess或者TerminateProcess函数中指定。
    2. main或者WinMain的返回值。
    3. 由于未处理的异常导致的结束,返回相应的异常值。

    一旦进程终止,就会如下事件发生:

    1. 所有被这个进程创建的或撕开的对象句柄就会关闭。
    2. 此进程内的所有线程将终止执行。
    3. 进程内核对象变成受信状态,所有等待在此对象上的线程开始运行,即WaitForSingleObject函数返回。
    4. 系统将进程对象中退出代码值由STILL_ACTIVE设置为指定的退出代码。
  • 相关阅读:
    Linux防火墙管理(iptables)以及开放端口配置
    CSS 样式引入方式、常用选择器以及优先级权重的计算
    初识外边距合并-margin collapsing
    纯CSS实现自适应正方形
    常用正则
    vue 学习记录
    VScode 之快速创建vue模板
    vscode之常用插件
    工具函数
    Axios之配置参数
  • 原文地址:https://www.cnblogs.com/furzoom/p/7710237.html
Copyright © 2011-2022 走看看