精华内容
下载资源
问答
  • Windows进程管理

    千次阅读 2018-05-30 22:59:16
    (2)通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解 Windows 进程的“一生”。 (3)通过阅读和分析实验程序,学习创建进程、观察进程、终止进程以及父子...

    一、实验目的

    (1)学会使用 VC 编写基本的 Win32 Consol Application(控制台应用程序)。

    (2)通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解 Windows 进程的“一生”。

    (3)通过阅读和分析实验程序,学习创建进程、观察进程、终止进程以及父子进程同步的基本程序设计方法。

    二、总体设计

       2.1背景知识

    Windows 所创建的每个进程都从调用 CreateProcess() API 函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。每一进程都以调用 ExitProcess() 或 TerminateProcess() API 函数终止。通常应用程序的框架负责调用 ExitProcess() 函数。对于 C++ 运行库来说,这一调用发生在应用程序的 main() 函数返回之后。

     

         (1)创建进程
         CreateProcess() 调用的核心参数是可执行文件运行时的文件名及其命令行。表 1-1 详细地列出了每个参数的类型和名称。

    表 1-1 CreateProcess() 函数的参数

    参数名称

    使用目的

    LPCTSTR lpApplivationName

    全部或部分地指明包括可执行代码的 EXE 文件的文件名

    LPCTSTR lpCommandLine

    向可执行文件发送的参数

    LPSECURIITY_ATTRIBUTES
    lpProcessAttributes

    返回进程句柄的安全属性。主要指明这一句柄是否应该由其他
    子进程所继承

    LPSECURIITY_ATTRIBUTES
    lpThreadAttributes

    返回进程的主线程的句柄的安全属性

    BOOL bInheritHandle

    一种标志,告诉系统允许新进程继承创建者进程的句柄

    DWORD dwCreationFlage

    特殊的创建标志 (CREATE_SUSPENDED) 的位标记

    LPVOID lpEnvironment

    向新进程发送的一套环境变量;如为 null 值则发送调用者环境

    LPCTSTR lpCurrentDirectory

    新进程的启动目录

    STARTUPINFO lpStartupInfo

    STARTUPINFO 结构,包括新进程的输入和输出配置的详情

    LPPROCESS_INFORMATION
    lpProcessInformation

    调用的结果块;发送新应用程序的进程和主线程的句柄和 ID

     

        可以指定第一个参数,即应用程序的名称,其中包括相对于当前进程的当前目录的全路径或者利用搜索方法找到的路径; lpCommandLine 参数允许调用者向新应用程序发送数据;接下来的三个参数与进程和它的主线程以及返回的指向该对象的句柄的安全性有关。

    然后是标志参数,用以在 dwCreationFlags 参数中指明系统应该给予新进程什么行为。经常使用的标志是 CREATE_SUSPNDED,告诉主线程立刻暂停。当准备好时,应该使用 ResumeThread() API来启动进程。另一个常用的标志是 CREATE_NEW_CONSOLE,告诉新进程启动自己的控制台窗口,而不是利用父窗口。这一参数还允许设置进程的优先级,用以向系统指明,相对于系统中所有其他
    的活动进程来说,给此进程多少 CPU 时间。
        接着是 CreateProcess() 函数调用所需要的三个通常使用缺省值的参数。第一个参数是lpEnvironment 参数,指明为新进程提供的环境;第二个参数是 lpCurrentDirectory,可用于向主创进程发送与缺省目录不同的新进程使用的特殊的当前目录;第三个参数是 STARTUPINFO 数据结构所必需的,用于在必要时指    

    明新应用程序的主窗口的外观。
        CreateProcess() 的最后一个参数是用于新进程对象及其主线程的句柄和 ID 的返回值缓冲区。以 PROCESS_INFORMATION 结构中返回的句柄调用 CloseHandle() API 函数是重要的,因为如果不将这些句柄关闭的话,有可能危及主创进程终止之前的任何未释放的资源。

     

    (2) 正在运行的进程
        如果一个进程拥有至少一个执行线程,则为正在系统中运行的进程。通常,这种进程使用主线程来指示它的存在。当主线程结束时,调用 ExitProcess() API 函数,通知系统终止它所拥有的所有正在运行、准备运行或正在挂起的其他线程。当进程正在运行时,可以查看它的许多特性,其中少数特性也允许加以修改。
        首先可查看的进程特性是系统进程标识符 (PID) ,可利用 GetCurrentProcessId() API 函数来查看,与 GetCurrentProcess() 相似,对该函数的调用不能失败,但返回的 PID 在整个系统中都可使用。其他的可显示当前进程信息的 API 函数还有 GetStartupInfo()和 GetProcessShutdownParameters() ,可给出进程存活期内的配置详情。

    通常,一个进程需要它的运行期环境的信息。例如 API 函数 GetModuleFileName() 和GetCommandLine() ,可以给出用在 CreateProcess() 中的参数以启动应用程序。在创建应用程序时可使用的另一个 API 函数是 IsDebuggerPresent() 。
        可利用 API 函数 GetGuiResources() 来查看进程的 GUI 资源。此函数既可返回指定进程中的打开的 GUI 对象的数目,也可返回指定进程中打开的 USER 对象的数目。进程的其他性能信息可通过GetProcessIoCounters()、GetProcessPriorityBoost() 、GetProcessTimes() 和 GetProcessWorkingSetSize()
    API 得到。以上这几个 API 函数都只需要具有 PROCESS_QUERY_INFORMATION 访问权限的指向所感兴趣进程的句柄。
        另一个可用于进程信息查询的 API 函数是 GetProcessVersion() 。此函数只需感兴趣进程的 PID(进程标识号) 。这一 API 函数与 GetVersionEx() 的共同作用,可确定运行进程的系统的版本号。


        (3) 终止进程
        所有进程都是以调用 ExitProcess() 或者 TerminateProcess() 函数结束的。但最好使用前者而不要使用后者,因为进程是在完成了它的所有的关闭“职责”之后以正常的终止方式来调用前者的。而外部进程通常调用后者即突然终止进程的进行,由于关闭时的途径不太正常,有可能引起错误的行为。
        TerminateProcess() API 函数只要打开带有 PROCESS_TERMINATE 访问权的进程对象,就可以终止进程,并向系统返回指定的代码。这是一种“野蛮”的终止进程的方式,但是有时却是需要的。如果开发人员确实有机会来设计“谋杀” (终止别的进程的进程) 和“受害”进程 (被终止的进程) 时,应该创建一个进程间通讯的内核对象——如一个互斥程序——这样一来,“受害”进程只在等待或周期性地测试它是否应该终止。


        (4)进程同步
        Windows 提供的常用对象可分成三类:核心应用服务、线程同步和线程间通讯。其中,开发人员可以使用线程同步对象来协调线程和进程的工作,以使其共享信息并执行任务。此类对象包括互锁数据、临界段、事件、互斥体和信号等。
        多线程编程中关键的一步是保护所有的共享资源,工具主要有互锁函数、临界段和互斥体等;另一个实质性部分是协调线程使其完成应用程序的任务,为此,可利用内核中的事件对象和信号。
        在进程内或进程间实现线程同步的最方便的方法是使用事件对象,这一组内核对象允许一个线程对其受信状态进行直接控制 (见表 1-2) 。
        而互斥体则是另一个可命名且安全的内核对象,其主要目的是引导对共享资源的访问。拥有单一访问资源的线程创建互斥体,所有想要访问该资源的线程应该在实际执行操作之前获得互斥体,而在访问结束时立即释放互斥体,以允许下一个等待线程获得互斥体,然后接着进行下去。
        与事件对象类似,互斥体容易创建、打开、使用并清除。利用 CreateMutex() API 可创建互斥体,创建时还可以指定一个初始的拥有权标志,通过使用这个标志,只有当线程完成了资源的所有的初始化工作时,才允许创建线程释放互斥体。

    表 1-2 用于管理事件对象的 API

    API 名称

    描述

    CreateEvent()

    在内核中创建一个新的事件对象。此函数允许有安全性设置、手工还是
    自动重置的标志以及初始时已接受还是未接受信号状态的标志

    OpenEvent()

    创建对已经存在的事件对象的引用。此 API 函数需要名称、继承标志和
    所需的访问级别

    SetEvent()

    将手工重置事件转化为已接受信号状态

    ResetEvent()

    将手工重置事件转化为非接受信号状态

    PulseEvent()

    将自动重置事件对象转化为已接受信号状态。当系统释放所有的等待它
    的线程时此种转化立即发生

     

    为了获得互斥体,首先,想要访问调用的线程可使用 OpenMutex() API 来获得指向对象的句柄;然后,线程将这个句柄提供给一个等待函数。当内核将互斥体对象发送给等待线程时,就表明该线程获得了互斥体的拥有权。当线程获得拥有权时,线程控制了对共享资源的访问——必须设法尽快地放弃互斥体。放弃共享资源时需要在该对象上调用 ReleaseMute() API。然后系统负责将互斥体拥有权传递给下一个等待着的线程 (由到达时间决定顺序) 。

     

    2.2 设计步骤

        (1)编写基本的 Win32 Consol Application
        步骤 1:登录进入 Windows 系统,启动 VC++ 6.0。
        步骤 2:在“FILE”菜单中单击“NEW”子菜单,在“projects”选项卡中选择“Win32 ConsolApplication”,然后在“Project name”处输入工程名,在“Location” 处输入工程目录。创建一个新的控制台应用程序工程。
        步骤 3:在“FILE”菜单中单击“NEW”子菜单,在“Files”选项卡中选择“C++ Source File”,然后在“File” 处输入 C/C++源程序的文件名。
        步骤 4:将清单 1-1 所示的程序清单复制到新创建的 C/C++源程序中。编译成可执行文件。
        步骤 5:在“开始”菜单中单击“程序”-“附件”-“命令提示符”命令,进入 Windows“命令提示符”窗口,然后进入工程目录中的 debug 子目录,执行编译好的可执行程序,列出运行结果(如果运行不成功,则可能的原因是什么?)
        (2) 创建进程
         本实验显示了创建子进程的基本框架。该程序只是再一次地启动自身,显示它的系统进程 ID和它在进程列表中的位置。
        步骤 1:创建一个“Win32 Consol Application”工程,然后拷贝清单 1-2 中的程序,编译成可执行文件。
        步骤 2:在“命令提示符”窗口运行步骤 1 中生成的可执行文件,列出运行结果。按下ctrl+alt+del,调用 windows 的任务管理器,记录进程相关的行为属性。
        步骤 3:在“命令提示符”窗口加入参数重新运行生成的可执行文件,列出运行结果。按下ctrl+alt+del,调用 windows 的任务管理器,记录进程相关的行为属性。
        步骤 4:修改清单 1-2 中的程序,将nClone的定义和初始化方法按程序注释中的修改方法进行修改,编译成可执行文件(执行前请先保存已经完成的工作)。再按步骤 2 中的方式运行,看看结果会有什么不一样。列出行结果。从中你可以得出什么结论?说明nClone的作用。 变量的定义和初始化方法(位置)对程序的执行结果有影响吗?为什么?
       (3) 父子进程的简单通信及终止进程
        步骤 1:创建一个“Win32 Consol Application”工程,然后拷贝清单 1-3 中的程序,编译成可执行文件。
        步骤 2:在 VC 的工具栏单击“Execute Program” (执行程序) 按钮,或者按 Ctrl + F5 键,或者在“命令提示符”窗口运行步骤 1 中生成的可执行文件,列出运行结果。
        步骤 3:按源程序中注释中的提示,修改源程序 1-3,编译执行(执行前请先保存已经完成的工作),列出运行结果。在程序中加入跟踪语句,或调试运行程序,同时参考 MSDN 中的帮助文件CreateProcess()的使用方法,理解父子进程如何传递参数。给出程序执行过程的大概描述。
        步骤 4:按源程序中注释中的提示,修改源程序 1-3,编译执行,列出运行结果。
        步骤 5:参 考 MSDN 中 的 帮 助 文 件 CreateMutex() 、 OpenMutex() 、 ReleaseMutex() 和WaitForSingleObject()的使用方法,理解父子进程如何利用互斥体进行同步的。给出父子进程同步过程的一个大概描述。

     

    三、详细设计

     

    清单 1-1

    // hello 项目
    # include <iostream>
    void main()
    {
    std::cout << "Hello, Win32 Consol Application" << std :: endl ;
    }

    清单 1-2

    #include <windows.h>
    #include <iostream>
    #include <stdio.h>
    // 创建传递过来的进程的克隆过程并赋于其 ID 值
    void StartClone(int nCloneID)
    {
    // 提取用于当前可执行文件的文件名
    TCHAR szFilename[MAX_PATH] ;
    GetModuleFileName(NULL, szFilename, MAX_PATH) ;
    // 格式化用于子进程的命令行并通知其 EXE 文件名和克隆 ID
    TCHAR szCmdLine[MAX_PATH];
    sprintf(szCmdLine,"\"%s\" %d",szFilename,nCloneID);
    // 用于子进程的 STARTUPINFO 结构
    STARTUPINFO si;
    ZeroMemory(&si , sizeof(si) ) ;
    si.cb = sizeof(si) ; // 必须是本结构的大小
    // 返回的用于子进程的进程信息
    PROCESS_INFORMATION pi;
    // 利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质
    BOOL bCreateOK=::CreateProcess(
    szFilename, // 产生这个 EXE 的应用程序的名称
    szCmdLine, // 告诉其行为像一个子进程的标志
    NULL, // 缺省的进程安全性
    NULL, // 缺省的线程安全性
    FALSE, // 不继承句柄
    CREATE_NEW_CONSOLE, // 使用新的控制台
    NULL, // 新的环境
    NULL, // 当前目录
    &si, // 启动信息
    &pi) ; // 返回的进程信息
    // 对子进程释放引用
    if (bCreateOK)
    {
    CloseHandle(pi.hProcess) ;
    CloseHandle(pi.hThread) ;
    }
    }
    int main(int argc, char* argv[] )
    {
    // 确定派生出几个进程,及派生进程在进程列表中的位置
    int nClone=0;
    //修改语句: int nClone;
    //第一次修改: nClone=0;
    nClone=0;
    if (argc > 1)
    {
    // 从第二个参数中提取克隆 ID
    :: sscanf(argv[1] , "%d" , &nClone) ;
    }
    //第二次修改: nClone=0;
    // 显示进程位置
    std :: cout << "Process ID:" << :: GetCurrentProcessId()
    << ", Clone ID:" << nClone
    << std :: endl;
    // 检查是否有创建子进程的需要
    const int c_nCloneMax=5;
    if (nClone < c_nCloneMax)
    {
    // 发送新进程的命令行和克隆号
    StartClone(++nClone) ;
    }
    // 等待响应键盘输入结束进程
    getchar();
    return 0;
    }

    清单 1-3

    // procterm 项目
    # include <windows.h>
    # include <iostream>
    # include <stdio.h>
    static LPCTSTR g_szMutexName = "w2kdg.ProcTerm.mutex.Suicide" ;
    // 创建当前进程的克隆进程的简单方法
    void StartClone()
    {
    // 提取当前可执行文件的文件名
    TCHAR szFilename[MAX_PATH] ;
    GetModuleFileName(NULL, szFilename, MAX_PATH) ;
    // 格式化用于子进程的命令行,字符串“ child”将作为形参传递给子进程的 main 函数
    TCHAR szCmdLine[MAX_PATH] ;
    //实验 1-3 步骤 3:将下句中的字符串 child 改为别的字符串,重新编译执行,执行前请先保存已经完成的工作
    sprintf(szCmdLine, "\"%s\"child" , szFilename) ;
    // 子进程的启动信息结构
    STARTUPINFO si;
    ZeroMemory(&si,sizeof(si)) ;
    si.cb = sizeof(si) ; // 应当是此结构的大小
    // 返回的用于子进程的进程信息
    PROCESS_INFORMATION pi;
    // 用同样的可执行文件名和命令行创建进程,并指明它是一个子进程
    BOOL bCreateOK=CreateProcess(
    szFilename, // 产生的应用程序的名称 (本 EXE 文件)
    szCmdLine, // 告诉我们这是一个子进程的标志
    NULL, // 用于进程的缺省的安全性
    NULL, // 用于线程的缺省安全性
    FALSE, // 不继承句柄
    CREATE_NEW_CONSOLE, //创建新窗口
    NULL, // 新环境
    NULL, // 当前目录
    &si, // 启动信息结构
    &pi ) ; // 返回的进程信息
    // 释放指向子进程的引用
    if (bCreateOK)
    {
    CloseHandle(pi.hProcess) ;
    CloseHandle(pi.hThread) ;
    }
    }
    void Parent()
    {
    	//当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。
    // 创建“自杀”互斥程序体
    HANDLE hMutexSuicide=CreateMutex(
    NULL, // 缺省的安全性
    TRUE, // 最初拥有的
    g_szMutexName) ; // 互斥体名称
    if (hMutexSuicide != NULL)
    {
    // 创建子进程
    std :: cout << "Creating the child process." << std :: endl;
    StartClone() ;
    // 指令子进程“杀”掉自身
    std :: cout << "Telling the child process to quit. "<< std :: endl;
    //等待父进程的键盘响应
    getchar() ;
    //释放互斥体的所有权,这个信号会发送给子进程的 WaitForSingleObject 过程
    ReleaseMutex(hMutexSuicide) ;
    // 消除句柄
    CloseHandle(hMutexSuicide) ;
    }
    }
    void Child()
    {
    // 打开“自杀”互斥体
    HANDLE hMutexSuicide = OpenMutex(
    SYNCHRONIZE, // 打开用于同步
    FALSE, // 不需要向下传递
    g_szMutexName) ; // 名称
    if (hMutexSuicide != NULL)
    {
    // 报告我们正在等待指令
    std :: cout <<"Child waiting for suicide instructions. " << std :: endl;
    //子进程进入阻塞状态,等待父进程通过互斥体发来的信号
    WaitForSingleObject(hMutexSuicide, INFINITE) ;
    //实验 1-3 步骤 4:将上句改为 WaitForSingleObject(hMutexSuicide, 0) ,重新编译执行
    //dwMilliseconds[in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。
    
    // 准备好终止,清除句柄
    std :: cout << "Child quiting." << std :: endl;
    CloseHandle(hMutexSuicide) ;
    }
    }
    int main(int argc, char* argv[] )
    {
    // 决定其行为是父进程还是子进程
    if (argc>1 && :: strcmp(argv[1] , "child" )== 0)
    {
    Child() ;
    }
    else
    {
    Parent() ;
    }
    return 0;
    }

    四、实验结果与分析

       (1)编写基本的 Win32 Consol Application

    运行结果:

     

       (2) 创建进程

    步骤二运行结果:

     

    进程相关属性:

     

     

    步骤三运行结果:加入参数n(n<=5),nClone ID n~5的6-n个进程

     

    Windows的任务管理器显示此6-n个进程。

     

     

    步骤四运行结果:程序进入死循环,无限创建进程。结论:nClone的值控制着创建的进程数。变量的定义和初始化对程序的执行结果有影响,因为如果初始化在判定语句内,程序会受其影响!

     

       (3) 父子进程的简单通信及终止进程

    步骤二运行结果:运行父子两个进程,在父进程中输入字符关闭子进程,形成父子进程的简单通信。

     

    步骤三运行结果:由于传入的参数与child不同,所以一直执行Parent();函数,一直创建子进程。创建子进程时,格式化用于子进程的命令行,字符串“ child”将作为形参传递给子进程的 main 函数(sprintf(szCmdLine, "\"%s\"child" , szFilename) ;)。

     

    步骤四运行结果:子进程一闪而过。/dwMilliseconds[in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。

     

     

    步骤五:

     

    CreateMutex()使用方法:

     

    HANDLE CreateMutex(

    LPSECURITY_ATTRIBUTESlpMutexAttributes, // 指向安全属性的指针

    BOOLbInitialOwner, // 初始化互斥对象的所有者

    LPCTSTRlpName // 指向互斥对象名的指针

    );

    创建一个互斥体(MUTEX)

    返回值:

    Long,如执行成功,就返回互斥体对象的句柄;零表示出错。会设置GetLastError。如果返回的是一个有效句柄,但指定的名字已经存在,GetLastError也会设为ERROR_ALREADY_EXISTS,bInitialOwner的值将会被忽略。如果调用者限制了权限,GetLastError将会返回ERROR_ACCESS_DENIED,这个时候应该使用OpenMutex函数。

    参数类型及说明:

    lpMutexAttributes SECURITY_ATTRIBUTES,指定一个SECURITY_ATTRIBUTES结构,或传递零值(将参数声明为ByVal As Long,并传递零值),表示使用不允许继承的默认描述符

    bInitialOwner BOOL,如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有

    lpName String,指定互斥体对象的名字。用vbNullString创建一个未命名的互斥体对象。如已经存在拥有这个名字的一个事件,则打开现有的已命名互斥体。这个名字可能不与现有的事件、信号机、可等待计时器或文件映射相符

     

     

    OpenMutex()使用方法:

     

    OpenMutex函数为现有的一个已命名互斥体对象创建一个新句柄。

    函数功能:

    函数原型: HANDLE OpenMutex(

    DWORD dwDesiredAccess// access

    BOOL bInheritHandle// inheritance option

    LPCTSTR lpName // object name

    );

    参数:

    dwDesiredAccess:

    MUTEX_ALL_ACCESS 请求对互斥体的完全访问

    MUTEX_MODIFY_STATE 允许使用 ReleaseMutex 函数

    SYNCHRONIZE 允许互斥体对象同步使用

    bInheritHandle : 如希望子进程能够继承句柄,则为TRUE

    lpName :要打开对象的名字

    返回值:

    如执行成功,返回对象的句柄;零表示失败。若想获得更多错误信息,请调用GetLastError函数。

     

     

    ReleaseMutex()使用方法:

     

     

    ReleaseMutex函数的功能是释放互斥对象的控制权

    函数原型:

    BOOL WINAPI ReleaseMutex(

    HANDLE hMutex

     

    );

    返回值:

     

    BOOL,TRUE表示成功,FALSE表示失败。

    参数表:

    hMutex:HANDLE,制定一个互斥体的句柄。

     

    WaitForSingleObject()使用方法:

     

    等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。

    WaitForSingleObject 函数

    DWORD WaitForSingleObject(

    HANDLE hObject,

              DWORD dwMilliseconds

    );

    第一个参数:hObject标识一个能够支持被通知/未通知的内核对象(前面列出的任何一种对象都适用)。

    第二个参数:dwMilliseconds允许该线程指明,为了等待该对象变为已通知状态,它将等待多长时间。(INFINITE为无限时间量,INFINITE已经定义为0xFFFFFFFF(或-1))

    传递INFINITE有些危险如果对象永远不变为已通知状态,那么调用线程永远不会被唤醒,它将永远处于死锁状态,不过,它不会浪费宝贵的C P U时间。

    父子进程同步过程的一个大概描述:父进程创建“自杀”互斥程序体,参数值为TRUE,最初拥有,函数最后父进程释放互斥体所有权。子进程OpenMutex();打开互斥体获得句柄,WaitForSingleObject(hMutexSuicide, INFINITE) ;等待对象信号,如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。终止时,CloseHandle(hMutexSuicide) ;消除句柄

    五、小结与心得体会

    通过本实验,我学会使用 VC 的 Win32 Consol Application(控制台应用程序)创建进程并且观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解 Windows 进程的“一生”。通过阅读和分析实验程序,我学会了创建进程、观察进程、终止进程以及父子进程同步的基本程序设计方法。

     

     

     

    展开全文
  • 我在做操作系统课程设计,请问怎么实现Windows进程管理
  • 对象、进程、线程是Windows2000三个基元成份,它们之间有互相交叉的关系。 1、对象 对象是一个抽象的数据结构,在Windows2000中用以表示广义的资源。它是构成OS的三个基元成份中非活动的成份,对象是数据和有关...

    一、Windows 2000的基元成分

    对象、进程、线程是Windows2000三个基元成份,它们之间有互相交叉的关系。

    1、对象

    对象是一个抽象的数据结构,在Windows2000中用以表示广义的资源。它是构成OS的三个基元成份中非活动的成份,对象是数据和有关操作的封装体,它包装数据、数据的属性以及可以施加于数据的操作等三个成份。具有相同特性的对象也可归为一个对象类,在软件设计中定义了对象类(称为类Class),而对象则是对象类一个具体实现的示例。对象作为抽象数据而封装在其内部的操作函数所提供的操作也给人活动成份的感觉,但是从操作系统这一角度来认识,对象是构成操作系统的非活动成份。而进程和线程则是构成OS的两个活动成份。

    Windows 2000中的实体,当数据或资源对用户态开放时,或者当数据访问是共享的或受限制时,才使用对象。采用对象方法表示的实体有文件、进程、线程、信号量、互斥量、事件、计时器等。Windows 2000通过对象管理器以一致的方法创建和管理所有的对象类型,对象管理器代表应用程序负责创建和删除对象,并负责授权访问对象的数据和服务。
    这里写图片描述
    每一个对象都有一个对象头和一个对象体。对象管理器控制对象头,各执行体组件控制它们自己创建的对象类型的对象体。当进程通过名称来创建或打开一个对象时,它会收到一个代表进程访问对象的句柄。所有用户态进程只有获得了对象句柄之后才可以使用这个对象。句柄作为系统资源的间接指针来使用,这种不直接的方式阻止了应用程序对系统数据结构直接地随便操作。

    2、进程

    Windows2000中进程被定义为表示OS所要做的工作,是OS用于组织其必须完成诸工作的一种手段。NT中的进程由一个可执行的程序、一个私用的虚地址空间、系统资源和至少一个执行线程等四部分组成。
    这里写图片描述
    NT的进程概念与传统OS进程概念有所不同,NT进程是作为对象来实现,因此从广义角度来说,进程也是共享的资源(多个用户进程可共享服务器进程提供的服务)。

    NT定义了一个进程对象类,进程的对象类的对象体和所包含的属性定义了进程对象的数据及其属性和施加其上的操作(服务),但描述进程组成的两个主要部分:进程地址空间和局限于进程的对象表,不包含在属性表中,因为它是附属的、不可见的。NT进程要求一个独特的组成成分:至少一个执行线程,这在传统OS中是没有的。NT进程的组成中没有进程控制块,有关进程的信息在进程对象的对象体中以及局限于进程的对象表中。
    这里写图片描述

    3、线程

    NT的线程是进程内的一个执行单元,是进程内的一个可调度实体。一个线程是由唯一的标识符客户ID、描述处理器状态的一组状态寄存器的内容、用户栈和核心栈、一个私用存贮器等四部分组成,线程也是作为对象来实现。每个进程创建时只有一个线程,需要时这个线程创建其它线程。线性是进程的一个组成部分,一个NT进程可以有多个线程在其地址空间内执行。资源分配的单位是进程,调度和执行的基本单位是线程。
    这里写图片描述

    二、Windows进程控制API函数

    1、CreateProcess函数

    当一个线程调用CreateProcess时,系统就会创建一个进程内核对象,为新进程创建一个虚拟地址空间,并将可执行文件加载到该进程的地址空间中。然后系统再为新进程的主线程创建一个线程内核对象。通过执行启动代码,该主线程便开始运行,它最终调用WinMain、wWinMain、main或wmain函数。如果系统成功地创建了新进程和主线程,该函数便返回TRUE。

    2、CreateThread函数

    CreateThread函数创建一个在调用进程的地址空间中执行的线程。
    格式:

    HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD  dwStacksize, LPTHREAD_START_ROUTINE lpStartAddress, 
    LPVOID tpParameter, DWORD dwCreationFlags, LPDWORD lpThreadld);

    lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构,该结构决定了返回的句柄是否可被子进程继承。若lpThreadAttributes为NULL,则句柄不能被继承。
    dwStackSize:定义原始堆栈提交时的大小(按字节计)。系统将该值舍入为最近的页。若该值为0,或小于默认时提交的大小,默认情况是使用与调用线程同样的大小。
    lpStartAddress:指向一个新线程执行的LPTHREAD_START_ROUTINE类型应用定义的函数。该指针还表示远程进程中线程的起始地址。该函数必须存在于远程进程中。
    lpParameter:定义一个传递给该新线程的32位值。
    dwCreationFiags:定义控制线程创建的附加标志。若定义了CREATE_SUSPENDED标志,线程创建时处于挂起状态,并且直到ResumeThread函数调用时才能运行。若该值为0,则该线程在创建后立即执行。
    lpThreadId:指向一个32位值,它接收该线程的标识符。
    返回值:若函数调用成功,返回值为新线程的句柄;若函数调用失败, 返回值为NULL。

    3、ExitThread函数

    ExitThread函数结束一个线程。
    格式:

    VOID ExitThread ( DWORD dwExitCode ) ;

    dwExitCode:定义调用线程的退出代码。使用GetExitCodeThread函数来检测一个线程的退出代码。
    返回值:无。
    SuspendThread()函数用于挂起指定的线程。
    ResumeThread()函数递减指定线程的挂起计数,挂起计数为0时,线程恢复执行。

    4、互斥对象函数

    在windows2000中提供了互斥对象、信号量对象和事件对象等同步对象和相应的系统调用,用于进程和线程的同步。这些同步对象都有一个用户指定的对象名称,不同进程用同样的对象名称来创建或打开对象,从而获得该对象在本进程的句柄。
    互斥对象(Mutex)就是互斥信号量,在一个时刻只能被一个线程使用,它用于进程、线程间的互斥。它的相关API函数包括:CreateMutex、OpenMutex和ReleaseMutex。

    • CreateMutex
      函数创建一个互斥对象,返回对象句柄。
    • OpenMutex
      函数为现有的一个已命名互斥体对象创建一个新句柄。
    • ReleaseMurex
      函数放弃指定互斥对象的所有权。

    5、信号量对象函数

    信号量对象(semaphore)就是资源信号量,初始值的取值在0到指定最大值之间,用于限制并发访问的线程数,也可用于进程、线程间的同步。它的相关API包括:CreateSemaphore、OpenSemaphore和ReleaseSemaphore。

    • CreateSemapore
      函数是创建一个有名或者无名信号量对象在输人参数中指定最大值和初值,返回对象句柄。
    • OpenSemaphore
      函数为现有的一个已命名信号机对象创建一个新句柄。
    • ReleaseSemaphore
      函数释放对信号量对象的占用,将指定信号对象的计数增加一个指定的数量。

    6、等待操作函数

    Windows 2000为对象提供了两个统一的等待操作函数WaitForSingleObjectWaitForMultipleObjiects。等待的对象包括:Change notification(改变通告);Console input(控制台输入);Event(事件);Job(作业);Mutex(互斥对象);Process(进程);Semaphore(信号量);Thread(线程);Waitable timer(可等待定时器)。函数决定等待条件是否被满足。如果等待条件并没有被满足,调用线程进入一个高效的等待状态,当等待满足条件时占用非常少的处理器时间。在运行前,一个等待函数修改同步对象类型的状态。修改仅发生在引起函数返回的对象身上。例如,信号的计数减1。一个线程通过调用等待函数拥有对象。创建该对象的线程也拥有对象,而不需要调用等待函数。

    7、临界区对象函数

    临界区对象只能用于在同一个进程内使用的临界区,同一个进程内各线程对它的访问是互斥进行的。把变量说明为CRITICAL_SECTION类型,就可作临界区使用。相关的API包括InitializeCriticalSection、EnterCriticalSection、TryEnterCriticalSection、LeaveCriticalSection和DeleteCriticalSection。

    • InitializeCriticalSection
      函数初始化临界区对象。
    • EnterCriticalSection
      函数是等待指定临界区对象的所有权。当调用线程被赋予所有权时,该函数返回。
    • TryEnterCriticalSection
      函数决不允许调用线程进入等待状态。它的返回值能够指明调用线程是否能够获得对资源的访问权。TryEnterCriticalSection发现该资源已经被另一个线程访问,它就返回FALSE。在其他所有情况下,它均返回TRUE。运用这个函数,线程能够迅速查看它是否可以访问某个共享资源,如果不能访问,那么它可以继续执行某些其他操作,而不必进行等待。
    • LeaveCriticalSection
      函数释放指定临界区对象的所有权
    • DeleteCriticalSection
      函数释放与临界区对象相关的所有系统资源。

    三、Windows 2000内部进程通信机制

    1、本地过程调用LPC

    Windows 2000的客户进程与服务器进程之间的通信采用消息传送,而消息传送必须经过执行体的本地过程调用LPC。LPC是一个用于高速信息传输的进程间的通信机构,LPC是一个灵活的、经过优化的“远程过程调用”(RPC)版本,(RPC是一种通过网络在客户与服务器进程之间传递信息的工业标准通信机制),在Win32 API下它是不可用的,它是一个只对Window 2000操作系统组件有效的内部机制。LPC被使用在一个服务器进程与该服务器的一个或多个客户进程之间。LPC提供了三种不同的消息传送方法:

    第一种方法适用于传送小于256B的消息。它将消息传给与服务器进程相连的端口对象,系统为每个端口对象设置有一个固定大小的消息队列,作为通信之用,此方法用于发送少于256字节的信息。这个方法类同于消息缓冲队列通信机制。

    第二种方法适用于传送大于256B的消息。它将消息指针传给与服务器进程相连的端口对象,并把消息存放在共享的主存区域中,消息大小受进程所分得的主存配额限制。消息传送的过程如下:当客户要传送大消息时,就由它自己创建一个称为主存区域的对象-主存共享的对象,LPC机制使得该地址空间为客户进程和服务器均可见,然后客户进程把大消息存放在该主存区域对象中;再向服务的的端口对象的消息队列中传送一个小消息指出所传送消息的大小和消息所在的地址指针。

    第三种方法适用于服务器想读或写大量数据而共享区又太小情况。数据可以直接从客户地址空间读出或向客户地址间写入。LPC组件提供了两个函数,服务器可以用它们来完成这些操作,以第一种方法发送的消息被用于同步正在传送的信息。

    LPC典型地应用于以下情况:服务器创建已命名的服务器直接端口对象。客户提出与这个端口连接的请求。如果同意该请求,客户通信端口和服务器通信端口就会被创建。客户得到客户通信端口的句柄,服务器得到服务器通信端口句柄。然后客户和服务器将为了它们之间的通信使用新的端口。

    2、多级反馈队列调度算法

    Windows2000采用可抢占动态优先级多级反馈就绪队列调度算法,Windows2000的调度单位是线程。2000执行体支持32级优先级,并将它们分成两类,实时优先级(16-31)和可变优先级(1-15),0级为系统保留,运行一个仅用于对系统中空闲物理页面进行清页的零页线程。每个优先级一个就绪队列,高序号队列为高优先级。实时优先级采用多级队列调度算法;可变优先级采用多级反馈队列调度算法,每个线程优先级变化范围是5级,可变优先级又分为高级、中上、中级、中下和空闲五类。
    这里写图片描述

    线程完整用完一个规定的时间片值时,重新赋予新时间片值时,优先级降一级(不低于基本优先级),放在相应优先级就绪队列的尾部;
    这里写图片描述

    线程由于调用等待函数而阻塞时,减少一个时间片,并依据等待事件类型提高优先级;如等待键盘事件比等待磁盘事件的提高幅度大。
    这里写图片描述
    在下列5种情况下,Windows 2000会提升线程的当前优先级:

    • I/O操作完成
    • 信号量或事件等待结束
    • 前台进程中的线程完成一个等待操作
    • 由于窗口活动而唤醒图形用户接口线程
    • 线程处于就绪状态超过一定时间,但没能进入运行状态(处理机饥饿)

    线程优先级提升的目的是改进系统吞吐量、响应时间等整体特征,解决线程调度策略中潜在的不公正性。但它也不是完美的,它并不会使所有应用都受益。Windows 2000永远不会提升实时优先级范围内(16至31)的线程优先级。

    四、操作系统结构设计

    1、操作系统采用结构程序设计的必要性

    由于操作系统日趋庞大,结构日益复杂,错误增加以至不可避免。在以后每个新版中都纠错。其次由于操作系统存在并发性,进程间执行序列数量巨大,推进序列不确定性,程序错误的某种表现形式不重复出现,可能使人误解为一次偶然性机器的故障。这给操作系统调试带来了困难。为了使操作系统高可靠、高效能、可理解和可修改,操作系统必须采用结构程序设计方法。

    2、模块接口法

    模块接口法是OS最早采用的一种结构程序设计方法,早期操作系统(IBM的OS)和小型OS(如MS-DOS)均属此类型。模块接口法把一个系统按功能分成若干个具有一定独立性和大小完成某方面功能的模块,并规定好各模块之间的接口。接着在明确每个模块的内部功能的基础上对它们进行独立设计。最后在各模块设计完成后按照模块间的接口关系,将所有模块逐步链接成一个大系统。

    模块接口法的优点是使OS设计实现模块化的基本结构程序设计方法,它增加了OS灵活性,便于修改和维护。但由于模块部接口复杂,使得系统的结构关系不清晰,因而使系统的可靠性降低。故又称模块接口法为无序模块法。

    3、层次结构法

    为了减少各模块之间无序调动、互相依赖关系,特别是清除循环现象,引入层次结构设计法。它将模块间无序调用变为有序调用,它把OS的所有功能模块,按功能流图的调用次序,排列成若干层,各层之间的模块只能是单向调用关系,即是只允许上层模块调用相邻下层模块。这样操作系统的结构清晰,而不构成循环,使系统的调试和验证变得容易。

    层次结构法采用自底向上法形成操作系统。它先在裸机上添加第一层精心编制的软件,形成比原来机器功能更强的机器,称为虚拟机A1。再经过几乎是穷尽无遗的测试后,就有较大把握确信虚拟机A1是正确的。然后,再在A1上增加一层精心编制的软件,形成功能更强、更接近于实际要求的虚拟机A2,再经过几乎是穷尽无遗的测试, …… ……如此一层一层地自底向上地铺设各软件层,每一层都实现若干功能,最后构成满足要求的虚拟机An。因此只要下层各模块设计是正确的,就为上层功能模块的设计提供了可靠基础,从而增加了系统的可靠性。

    1968年Dijkstra在ELX8机器上编制的操作系统THE中采用各层间单向依赖,层内各模块互相独立的全序的层次关系设计。但该系统通信开销大,系统经过层层调用效率低,该设计方法不适用大型OS。在大层OS中要建立一个全序的层次结构关系是十分困难,往往无法避免循环现象。因些层次结构设计应作为OS设计的原则,尽可能将操作系统各功能模块排成有序层次,以便尽量减少系统中循环现象。

    4、客户-服务器方式

    操作系统结构技术的发展是与整个计算机技术的发展相联系的。当前技术发展的突出特点是要求广泛的信息和其它资源的共享,这一要求促使网络技术的普遍应用和发展。由于网络技术逐渐成熟,并实用化,再加以数据库联网已是应用的新趋势,为用户提供一个符合企业信息处理应用要求的分布式处理的系统环境是应用潮流的需要。操作系统采用客户/服务器结构,它将非常适应于分布式处理的计算机环境中,所以说C/S模式是第三代操作系统。

    客户/服务器C/S结构的思想是把操作系统分成内核和若干个进程。内核运行在核心态,负责调度、原语操作和中断处理等操作系统基本功能。每个进程实现单个的一套服务(例如:主存服务、进程生成服务等),称为服务器进程。每个服务运行在用户态,它执行一个循环以检查是否有客户已请求某项服务。而客户可以是另外的操作系统成分,也可以是应用程序。客户通过发送一个消息给服务器进程来请求提供一项服务。操作系统内核把该消息传送给服务器进程,而后该服务器执行有关的操作,操作完成后,内核用另一个消息把结果返回给客户进程。C/S结构模式的操作系统有卡内基.梅隆大学研制的Mach 操作系统和美国微软公司研制的WindowsNT操作系统。

    5、微内核模式

    对于一些专用的系统,主要是实时系统和“嵌入式”系统, “微内核”的思想就很有吸引力。究其原因,主要是因为通常这些系统都不带磁盘,整个系统都必须放在EPROM中,常常受到存储空间的限制,而所需要的服务又比较单一和简单。所以,几乎所有的嵌入式系统和实时系统都采用微内核,如PSOS,VxWorks等。
    优点:

    • 良好的扩充性:只需添加支持新功能的服务进程即可
    • 可靠性好:调用关系明确,执行转移不易混乱
    • 便于网络服务,实现分布式处理:以同样的调用形式,在下层可通过核心中的网络传送到远方服务器上 (远地过程调用 RPC)。

    缺点:将这些服务的提供都放在进程层次上,再通过进程间通信(通常是报文传递)提供服务,势必增加系统的运行开销,降低了效率,消息传递比直接调用效率要低一些 (但可以通过提高硬件性能来补偿 )。

    6、NT执行体

    运行在核心态内核的WindowsNT称为NT执行体。NT执行体结构是层次式与微内核的结合,它比UNIX内核小。基本上是一个完整的操作系统,它由一组部件构成,这些部件形成了层次结构。NT最底层是硬件抽象层(HAL),它将NT执行体的其余部分与运行机器硬件特性隔离开来。NT内核是第二层,它类拟于Mach的微内核,它负责对中断和异常作出响应;调度线程,提供一组基本对象和接口。

    NT内核上是一组部件:对象管理程序、安全调用监视程序、进程管理程序、本地过程调用功能和虚拟内存管理程序等。I/O系统内部又分成若干层,它们是由I/O管理程序、文件系统、高速缓冲存储管理程序、设备驱动程序、网络重定向程序和网络服务器等组成。NT执行体最上层系统服务是NT执行体为用户态的进程提供的一个接口

    7、保护子系统

    WindowsNT 操作系统除NT执行体外,操作系统所有的其它部分被分成若干个相对独立的进程,每一个进程实现一组服务,称为服务器进程,它运行在用户态。用户态服务器进程又称保护子系统。WindowsNT有二类保护子系统:环境子系统和集成子系统。

    环境子系统有Win32子系统、OS/2子系统和POSIX子系统几种,每种子系统为特定的操作系统提供一个API。它为客户进程提供服务是这样的:当一个应用程序调用其相应的某个API(本系统提供Win32、OS/2、POSIX、16位Windows和MS-DOS等系统的编程接口API)时,一个消息通过NT执行体的本地过程调用(LPC)工具,发送给完成该API程序的服务器进程-环境子系统。子系统执行API例程、并通过LPC将结果返回应用程序进程。

    集成子系统是完成重要操作系统功能的服务器。这包括安全子系统,网络软件中的若干部件(工作站服务和网络服务器服务)。当用户试图进入系统时,首先必须进行登录,由安全子系统对用户进行是否允许其进入和权限检查与控制。安全子系统维护着一个有关帐号信息数据库,内容包括帐号名、保密字、用户权限等信息。任何非法用户或非法操作,都被安全系统拒之门外。

    这里写图片描述

    这里写图片描述

    展开全文
  • 场景:在我们卸载程序时,常常有些残留文件保留在安装路径下,我们进入目录进一步做删除清理时,发现文件被占用,却不知道什么进程占用,接着我们就可利用微软公司提供的这么一款工具来解决我们的问题。 下载地址: ...

    场景:在我们卸载程序时,常常有些残留文件保留在安装路径下,我们进入目录进一步做删除清理时,发现文件被占用,却不知道什么进程占用,接着我们就可利用微软公司提供的这么一款工具来解决我们的问题。

    下载地址:
    https://docs.microsoft.com/zh-cn/sysinternals/downloads/handle

    在这里插入图片描述

    解压文件后打开是这样:
    在这里插入图片描述
    以第一个文本文件是软件相关协议的声明,handle.exe可执行文件兼容64位和32位机器,handle64.exe一般只能在64位机器运行,在这里我们使用handle.exe,配置环境变量:
    1、右键此电脑,点击属性

    2、点击高级系统设置

    3、点击环境变量在这里插入图片描述
    4、用户变量(只作用于当前登录用户)和环境变量(全局)类似,这里我配置用户变量,编辑Path环境变量
    在这里插入图片描述

    5、点击新建,输入handle.exe的文件路径
    如我解压后的文件路径:
    在这里插入图片描述
    Path变量内容:
    在这里插入图片描述

    6、点击确定

    7、运行cmd,输入命令"handle",接着弹出类似软件协议的对话框,点击Agree,然后会自动进行配置,稍等几秒。然后我们做测试
    ,比如我在D:\Handle下新建了一个Word文档,
    在这里插入图片描述
    用Word打开,然后删除该文件,出现对话框
    在这里插入图片描述

    在dos下我们直接输入命令"handle Handle.docx",输出显示:
    在这里插入图片描述

    接着用到DOS命令tasklist用来结束进程:
    在这里插入图片描述
    接着再次删除文档,就可成功删除了,当然,知道了进程名,就可以在任务管理器结束进程了,但在dos下的进程名与任务管理器的进程名又有点差异,如
    WINWORD.EXE

    在这里插入图片描述
    但都是对应同一个PID(唯一性),所以怕结束错进程,就用taskkill命令吧。

    展开全文
  • Python管理Windows进程

    千次阅读 2016-12-31 21:44:41
    Python管理Windows进程

    Python管理Windows进程

    字数1936 阅读1650 评论0 

    用python获得正在的运行的windows进程的有几种方式:

    方式一

    通过 PyWin32包对Windows进行处理。
    可以通过这个获取系统信息,但仅限于windows系统。

    import win32com.client
    wmi=win32com.client.GetObject('winmgmts:')
    for p in wmi.InstancesOf('win32_process'):
        print p.Name, p.Properties_('ProcessId'), \
            int(p.Properties_('UserModeTime').Value)+int(p.Properties_('KernelModeTime').Value)
        children=wmi.ExecQuery('Select * from win32_process where ParentProcessId=%s' %p.Properties_('ProcessId'))
        for child in children:
            print '\t',child.Name,child.Properties_('ProcessId'), \
                int(child.Properties_('UserModeTime').Value)+int(child.Properties_('KernelModeTime').Value)

    运行结果:

    System Idle Process 0 11055150937500
        System Idle Process 0 11055150937500
        System 4 14906718750
    System 4 14906718750
        smss.exe 864 937500
    smss.exe 864 937500
        csrss.exe 916 1752187500
        winlogon.exe 940 72812500
    csrss.exe 916 1752187500
    winlogon.exe 940 72812500
        services.exe 1024 324236406250
        lsass.exe 1044 10099062500
    services.exe 1024 324236406250
        svchost.exe 1236 35468750
        svchost.exe 1304 6174687500
        svchost.exe 1480 198943593750
        svchost.exe 1524 35156250
        svchost.exe 1636 1412656250
        svchost.exe 1688 494843750
        spoolsv.exe 1860 45312500
        DhMachineSvc.exe 2040 23593750
        jqs.exe 200 11605000000
        NTFSWatcher.exe 248 15625000
        OmniAddrService.exe 268 86406250
        pcas.exe 396 172187500
        nssm.exe 696 2968750
        TeamViewer_Service.exe 772 172343750
        winvnc4.exe 844 78750000
        svchost.exe 880 151718750
        alg.exe 3208 56093750
    lsass.exe 1044 10099062500
    svchost.exe 1236 35468750
        wmiprvse.exe 5184 2500000
    svchost.exe 1304 6174687500
    svchost.exe 1480 198943125000
    svchost.exe 1524 35156250
    svchost.exe 1636 1412656250
    svchost.exe 1688 494843750
    spoolsv.exe 1860 45312500
    DhMachineSvc.exe 2040 23593750
    jqs.exe 200 11605000000
    GoogleUpdate.exe 208 105312500
    NTFSWatcher.exe 248 15625000
    OmniAddrService.exe 268 86406250
    pcas.exe 396 172187500
    nssm.exe 696 2968750
        salt-minion.exe 716 79062500
    salt-minion.exe 716 79062500
    TeamViewer_Service.exe 772 172343750
    winvnc4.exe 844 78750000
    svchost.exe 880 151718750
    explorer.exe 1452 7501250000
        TSVNCache.exe 2496 114531250
        ctfmon.exe 2540 82343750
        chrome.exe 2556 25053125000
        RocketDock.exe 2564 411406250
        Xshell.exe 5200 12957656250
        mstsc.exe 8468 227500000
        iexplore.exe 7672 13281250
        cmd.exe 9404 312500
        sublime_text.exe 8920 131093750
        notepad.exe 2248 1718750
    TSVNCache.exe 2496 114531250
    ctfmon.exe 2540 82343750
    chrome.exe 2556 25053125000
        chrome.exe 3880 24531250
        chrome.exe 3872 52500000
        chrome.exe 2020 331093750
        chrome.exe 1028 35937500
        chrome.exe 196 37187500
        chrome.exe 184 55625000
        chrome.exe 2736 37656250
        chrome.exe 2752 1755781250
        chrome.exe 2772 83281250
        chrome.exe 2976 258125000
        SogouFlash.exe 3580 640468750
        SogouCloud.exe 3488 115625000
        SGImeGuard.exe 4300 24218750
        chrome.exe 3700 40312500
        chrome.exe 9148 3741406250
        chrome.exe 8496 7201250000
        chrome.exe 6840 200312500
        SogouSmartInfo.exe 9852 468750
    RocketDock.exe 2564 411406250
    alg.exe 3208 56093750
    chrome.exe 3880 24531250
    chrome.exe 3872 52500000
    chrome.exe 2020 331093750
    chrome.exe 1028 35937500
    chrome.exe 196 37187500
    chrome.exe 184 55625000
    chrome.exe 2736 37656250
    chrome.exe 2752 1755781250
    chrome.exe 2772 83281250
    chrome.exe 2976 258125000
    TaobaoProtect.exe 3772 27562812500
    conime.exe 388 59218750
    SogouFlash.exe 3580 640468750
    SogouCloud.exe 3488 115625000
    SGImeGuard.exe 4300 24218750
    Xshell.exe 5200 12957656250
    chrome.exe 3700 40312500
    aliwssv.exe 7160 46875000
    TM.exe 9144 2396250000
    chrome.exe 9148 3741250000
    Alipaybsm.exe 9536 73593750
    chrome.exe 8496 7199843750
    mstsc.exe 8468 227500000
    iexplore.exe 7672 13281250
        iexplore.exe 7256 148593750
    iexplore.exe 7256 148437500
    cmd.exe 9404 312500
        python.exe 9048 1875000
    sublime_text.exe 8920 127968750
        plugin_host.exe 9840 32031250
    plugin_host.exe 9840 30625000
        cmd.exe 6384 156250
    python.exe 9048 1875000
    notepad.exe 2248 1718750
    chrome.exe 6840 200312500
    SogouSmartInfo.exe 9852 468750
    cmd.exe 6384 156250
        python.exe 9584 10312500
    python.exe 9584 1093750
    wmiprvse.exe 5184 781250

    上面的从左到右分别是 进程名pid,cpu的运行时间

    方式二:

    import win32pdh, string, win32api
    
    def procids():
        #each instance is a process, you can have multiple processes w/same name
        junk, instances = win32pdh.EnumObjectItems(None,None,'process', win32pdh.PERF_DETAIL_WIZARD)
        proc_ids=[]
        proc_dict={}
        for instance in instances:
            if instance in proc_dict:
                proc_dict[instance] = proc_dict[instance] + 1
            else:
                proc_dict[instance]=0
        for instance, max_instances in proc_dict.items():
            for inum in xrange(max_instances+1):
                hq = win32pdh.OpenQuery() # initializes the query handle 
                path = win32pdh.MakeCounterPath( (None,'process',instance, None, inum,'ID Process') )
                counter_handle=win32pdh.AddCounter(hq, path) 
                win32pdh.CollectQueryData(hq) #collects data for the counter 
                type, val = win32pdh.GetFormattedCounterValue(counter_handle, win32pdh.PDH_FMT_LONG)
                proc_ids.append((instance,str(val)))
                win32pdh.CloseQuery(hq) 
    
        proc_ids.sort()
        return proc_ids
    
    print procids()

    运行结果:

    [(u'Alipaybsm', '9536'), (u'DhMachineSvc', '2040'), (u'GoogleUpdate', '208'), (u'Idle', '0'), (u'NTFSWatcher', '248'), (u'OmniAddrService', '268'), (u'RocketDock', '2564'), (u'SGImeGuard', '4300'), (u'SogouCloud', '3488'), (u'SogouFlash', '3580'), (u'SogouSmartInfo', '9852'), (u'System', '4'), (u'TM', '9144'), (u'TSVNCache', '2496'), (u'TaobaoProtect', '3772'), (u'TeamViewer_Service', '772'), (u'Xshell', '5200'), (u'_Total', '0'), (u'alg', '3208'), (u'aliwssv', '7160'), (u'chrome', '1028'), (u'chrome', '184'), (u'chrome', '196'), (u'chrome', '2020'), (u'chrome', '2556'), (u'chrome', '2736'), (u'chrome', '2752'), (u'chrome', '2772'), (u'chrome', '2976'), (u'chrome', '3700'), (u'chrome', '3872'), (u'chrome', '3880'), (u'chrome', '6840'), (u'chrome', '8496'), (u'chrome', '9148'), (u'cmd', '9404'), (u'cmd', '9776'), (u'conime', '388'), (u'csrss', '916'), (u'ctfmon', '2540'), (u'explorer', '1452'), (u'iexplore', '7256'), (u'iexplore', '7672'), (u'jqs', '200'), (u'lsass', '1044'), (u'mstsc', '8468'), (u'notepad', '2248'), (u'nssm', '696'), (u'pcas', '396'), (u'plugin_host', '9840'), (u'python', '3540'), (u'python', '9048'), (u'salt-minion', '716'), (u'services', '1024'), (u'smss', '864'), (u'spoolsv', '1860'), (u'sublime_text', '8920'), (u'svchost', '1236'), (u'svchost', '1304'), (u'svchost', '1480'), (u'svchost', '1524'), (u'svchost', '1636'), (u'svchost', '1688'), (u'svchost', '880'), (u'winlogon', '940'), (u'winvnc4', '844')]
    [Finished in 0.3s]

    获得 一个进程名进程Id元组的列表

    方式三:

    # http://code.activestate.com/recipes/305279/
    
    """
    Enumerates active processes as seen under windows Task Manager on Win NT/2k/XP using PSAPI.dll
    (new api for processes) and using ctypes.Use it as you please.
    
    Based on information from http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q175030&ID=KB;EN-US;Q175030
    
    By Eric Koome
    email ekoome@yahoo.com
    license GPL
    """
    from ctypes import *
    
    #PSAPI.DLL
    psapi = windll.psapi
    #Kernel32.DLL
    kernel = windll.kernel32
    
    def EnumProcesses():
        arr = c_ulong * 256
        lpidProcess= arr()
        cb = sizeof(lpidProcess)
        cbNeeded = c_ulong()
        hModule = c_ulong()
        count = c_ulong()
        modname = c_buffer(30)
        PROCESS_QUERY_INFORMATION = 0x0400
        PROCESS_VM_READ = 0x0010
    
        #Call Enumprocesses to get hold of process id's
        psapi.EnumProcesses(byref(lpidProcess),
                            cb,
                            byref(cbNeeded))
    
        #Number of processes returned
        nReturned = cbNeeded.value/sizeof(c_ulong())
    
        pidProcess = [i for i in lpidProcess][:nReturned]
    
        for pid in pidProcess:
    
            #Get handle to the process based on PID
            hProcess = kernel.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                                          False, pid)
            if hProcess:
                psapi.EnumProcessModules(hProcess, byref(hModule), sizeof(hModule), byref(count))
                psapi.GetModuleBaseNameA(hProcess, hModule.value, modname, sizeof(modname))
                print "".join([ i for i in modname if i != '\x00'])
    
                #-- Clean up
                for i in range(modname._length_):
                    modname[i]='\x00'
    
                kernel.CloseHandle(hProcess)
    
    if __name__ == '__main__':
        EnumProcesses()

    运行结果:

    smss.exe
    winlogon.exe
    services.exe
    lsass.exe
    svchost.exe
    svchost.exe
    svchost.exe
    spoolsv.exe
    DhMachineSvc.exe
    jqs.exe
    GoogleUpdate.exe
    NTFSWatcher.exe
    OmniAddrService.exe
    pcas.exe
    nssm.exe
    salt-minion.exe
    TeamViewer_Service.exe
    WinVNC4.exe
    svchost.exe
    Explorer.EXE
    TSVNCache.exe
    ctfmon.exe
    chrome.exe
    RocketDock.exe
    chrome.exe
    chrome.exe
    chrome.exe
    chrome.exe
    chrome.exe
    chrome.exe
    chrome.exe
    chrome.exe
    chrome.exe
    chrome.exe
    TaobaoProtect.exe
    conime.exe
    SogouFlash.exe
    SogouCloud.exe
    SGImeGuard.exe
    Xshell.exe
    chrome.exe
    aliwssv.exe
    TM.exe
    chrome.exe
    Alipaybsm.exe
    chrome.exe
    mstsc.exe
    iexplore.exe
    iexplore.exe
    cmd.exe
    sublime_text.exe
    plugin_host.exe
    python.exe
    NOTEPAD.EXE
    chrome.exe
    chrome.exe
    SogouSmartInfo.exe
    cmd.exe
    python.exe

    通过交互模式,使用WMI取得进程:

    # http://mail.python.org/pipermail/python-win32/2003-December/001482.html
    >>> import wmi
    >>> processes = wmi.WMI().InstancesOf('Win32_Process')
    >>> len(processes)
    41
    >>> [process.Properties_('Name').Value for process in processes] # get
    the process names
    [u'System Idle Process', u'System', u'SMSS.EXE', u'CSRSS.EXE',
    u'WINLOGON.EXE', u'SERVICES.EXE', u'LSASS.EXE', u'SVCHOST.EXE',
    u'SVCHOST.EXE', u'SVCHOST.EXE', u'SVCHOST.EXE', u'SPOOLSV.EXE',
    u'ati2evxx.exe', u'BAsfIpM.exe', u'defwatch.exe', u'inetinfo.exe',
    u'mdm.exe', u'rtvscan.exe', u'SCARDSVR.EXE', u'WLTRYSVC.EXE',
    u'BCMWLTRY.EXE', u'EXPLORER.EXE', u'Apoint.exe', u'carpserv.exe',
    u'atiptaxx.exe', u'quickset.exe', u'DSentry.exe', u'Directcd.exe',
    u'vptray.exe', u'ApntEx.exe', u'FaxCtrl.exe', u'digstream.exe',
    u'CTFMON.EXE', u'wuauclt.exe', u'IEXPLORE.EXE', u'Pythonwin.exe',
    u'MMC.EXE', u'OUTLOOK.EXE', u'LineMgr.exe', u'SAPISVR.EXE',
    u'WMIPRVSE.EXE']
    
    # Here is how to get a single process and get its PID.
    
    >>> p = wmi.WMI().ExecQuery('select * from Win32_Process where
    Name="Pythonwin.exe"')
    >>> [prop.Name for prop in p[0].Properties_] # let's look at all the
    process property names
    [u'Caption', u'CommandLine', u'CreationClassName', u'CreationDate',
    u'CSCreationClassName', u'CSName', u'Description', u'ExecutablePath',
    u'ExecutionState', u'Handle', u'HandleCount', u'InstallDate',
    u'KernelModeTime', u'MaximumWorkingSetSize', u'MinimumWorkingSetSize',
    u'Name', u'OSCreationClassName', u'OSName', u'OtherOperationCount',
    u'OtherTransferCount', u'PageFaults', u'PageFileUsage',
    u'ParentProcessId', u'PeakPageFileUsage', u'PeakVirtualSize',
    u'PeakWorkingSetSize', u'Priority', u'PrivatePageCount', u'ProcessId',
    u'QuotaNonPagedPoolUsage', u'QuotaPagedPoolUsage',
    u'QuotaPeakNonPagedPoolUsage', u'QuotaPeakPagedPoolUsage',
    u'ReadOperationCount', u'ReadTransferCount', u'SessionId', u'Status',
    u'TerminationDate', u'ThreadCount', u'UserModeTime', u'VirtualSize',
    u'WindowsVersion', u'WorkingSetSize', u'WriteOperationCount',
    u'WriteTransferCount']
    >>> p[0].Properties_('ProcessId').Value # get our ProcessId
    928

    方式四:

    此方法可以跨平台,不过需要在安装psutil包.

    import os
    import psutil
    import time
    
    logPath = r'some\path\proclogs'
    if not os.path.exists(logPath):
        os.mkdir(logPath)
    
    separator = "-" * 80
    format = "%7s %7s %12s %12s %30s, %s"
    format2 = "%7.4f %7.2f %12s %12s %30s, %s"
    while 1:
      # psutil.get_process_list() 方法已经废弃,可以使用psutil.process_iter()迭代器
    
        procs = psutil.get_process_list()
        procs = sorted(procs, key=lambda proc: proc.name)
    
        logPath = r'some\path\proclogs\procLog%i.log' % int(time.time())
        f = open(logPath, 'w')
        f.write(separator + "\n")
        f.write(time.ctime() + "\n")
        f.write(format % ("%CPU", "%MEM", "VMS", "RSS", "NAME", "PATH"))
        f.write("\n")
    
        for proc in procs:
            cpu_percent = proc.get_cpu_percent()
            mem_percent = proc.get_memory_percent()
            rss, vms = proc.get_memory_info()
            rss = str(rss)
            vms = str(vms)
            name = proc.name
            path = proc.path
            f.write(format2 % (cpu_percent, mem_percent, vms, rss, name, path))
            f.write("\n\n")
        f.close()
        print "Finished log update!"
        time.sleep(300)
        print "writing new log data!"

    以上实现一个类似top的工具。

    转自 http://www.blog.pythonlibrary.org/2010/10/03/how-to-find-and-list-all-running-processes-with-python/

    展开全文
  • Windows任务管理器 explorer 进程

    千次阅读 2018-04-03 16:45:26
    今天,不小心结束了windows任务管理器中的 explorer 进程,然后电脑桌面就什么都没有了……于是便了解了下explorer 进程……windows任务管理器的 explorer 进程windows的桌面进程,当遇到桌面卡住,或者刷新很慢...
  • Windows进程的创建与销毁

    千次阅读 2017-10-23 11:37:02
    今天课上做了关于进程创建与控制的实验,简单记录下来:实验题目 ① 掌握Windows进程的... ③ 通过Windows进程管理器查看系统进程列表的变化。 实验指导 ①创建进程的API BOOL CreateProcess( LPCTSTR lpApplic
  • windows 任务管理器,查看进程id,进程标识符pid。 任务管理器默认只显示了几列常用的属性,如果要看进程id等属性,需要我们设置让它显示出来。 操作方法如下: 进入任务管理器后,点击查看,再点击选择列。 勾选 ...
  • Qt:Windows编程—Qt实现进程管理

    千次阅读 2019-01-20 23:04:44
    继续学window编程,学呀学呀 学无止境,学到Windows进程相关API了。利用相关的API使用Qt写界面实现了一个简单的进程管理。主要用到 进程的创建、进程的枚举、线程的枚举、DLL的枚举、进程提权等功能。相关API的介绍...
  • Windows进程查找

    千次阅读 2019-09-04 20:23:05
    Windows下根据名称查找进程 使用vs调试C++程序时,有时由于强制退出,会出现 ***.exe无法写入 的错误,重启vs甚至都无法解决。 原因 由于调试强制结束,导致***.exe进程还在后台运行。 解决办法 打开命令提示符,...
  • Windows任务管理器同名进程批量删除

    千次阅读 2016-03-07 22:59:07
    Windows通过cmd终端批量删除同名进程
  • 上一次我们对Windows服务进行了简单的管理,学习了获取本地及远程计算机上服务的方法,以及查找...本次我们来关注一下Windows管理中另一个核心内容:进程管理。 测试脚本下载 本系列所有脚本均在Windows Server
  • Windows PowerShell 2.0之进程管理

    千次阅读 2010-12-18 00:46:00
    进程在操作系统中用于处理数据和进程间的交换,PowerShell的进程和服务管理机制能分析进程信息,并且直接操作进程实例指向的对象。这样对象化的命令为用户在提取数据及修改状态方面提供了方便,管道命令的优点结合...
  • windows进程切换-时间片管理

    千次阅读 2019-06-06 16:38:36
  • windows管理java进程

    千次阅读 2012-12-18 15:33:09
    今天要说的是,当一台windows服务器上单独运行了多个java程序的话,如何进行更好的管理。   首先,是在windows下运行java程序的启动脚本:   Cmd代码  java -classpath 需要加入classpath...
  • Windows进程控制

    千次阅读 2016-07-14 19:30:39
    Windows系统中,应用程序都以进程的形式存在于内存中。当运行一个程序的时候,操作系统就会将这个程序装入内存,并分配各种运行程序所需的资源,为进程创建主线程。 系统也提供了任务管理器,可供我们使用。管理...
  • C++ Windows进程控制

    万次阅读 2018-09-30 15:46:31
    一、杀死指定进程 // 杀死指定进程 BOOL KillProcessFromName(CString strProcessName) { HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof...
  • Windows下 wmic process命令进程管理

    千次阅读 2013-02-24 23:04:29
     WMIC扩展WMI(Windows Management Instrumentation,Windows管理规范) ,提供了从命令行接口和批命令脚本执行系统管理的支持。为WMI名称空间提供了一个强大的、友好的命令行接口。 ============================...
  • Windows进程详解(完整版)

    千次阅读 2019-03-27 15:47:17
    Windows进程详解(完整版)
  • Windows任务管理器中所有进程资料

    千次阅读 2008-03-08 19:03:00
    Windows任务管理器中所有进程资料 各位朋友们,想知道在自己的电脑中有哪些进程是没用的吗?看看下面的详细进程资料就可以得出答案: 1.进程文件: [system process] or [system process] 进程名称: Windows内存处理...
  • 一个简单的windows HOOK - 隐藏进程管理器中特定的进程 (适用平台:windows 2000 sp4,windows XP sp2) 屏蔽任务管理器中的进程名称有很多种方法,可以在ring0级做文章:修改内核进程链表,拦截内核API等。...
  • zabbix监控windows进程

    千次阅读 2019-06-28 14:46:08
    zabbix监控windows进程 一、目的:实现zabbix 3.0监控windows Server系统中特定进程(包括运行时间) 从网上查了很多资料,有人说用监控模版中的proc.mem或者proc.num或者proc_info,我们先看看这几个监控项: 1...
  • windows进程详解

    千次阅读 2004-11-04 15:31:00
    windows进程详解象进程,驱动安装等很多时候都无法界定该在软件版发还是在硬件版发,因为软件和硬件是有关联的Windows 2000/XP 的任务管理器是一个非常有用的工具,它能提供我们很多信息,比如现在系统中运行的程序...
  • windows进程间通信

    千次阅读 2014-10-18 08:32:03
    摘 要: 随着人们对应用程序的要求越来越高,单进程应用在许多场合已不能满足人们的要求。编写多进程/多线程程序成为现代程序设计的一个重要特点,在多进程程序设计中,进程间的通信是不可避免的。Microsoft Win32...
  • 其实对于 windows进程的操作很简单,只要理解了 进程线程的概念 对于 进程的操作 那么就只是 几个函数的 问题了 。 下面是 对于进程操作要用到的几个函数 。 进程的概念:我们运行了一个程序,那个这个独立的程序...
  • 1、用tasklist列出当前系统进程2、用taskkill /PID PID杀死进程,如果此进程需强制杀死,则加个/F参数,如:taskkill /F /PID PID3、注意:如果对命令的参数不熟悉的话,可以尝试使用tasklist /?来查看帮助,就相当...
  • Windows 进程的句柄表

    千次阅读 2015-03-12 14:49:32
    本文源自《Windows内核原理与实现》第3章Windows 进程和线程 3.4.1 Windows 进程的句柄表(1) 上一章介绍了Windows 内核中的对象管理器,Windows 执行体实现了一套对象机制来管理各种资源或实体。每种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 337,676
精华内容 135,070
关键字:

windows进程管理