Windows API(二)进程

Windows API笔记(一)内核对象
Windows API笔记(二)进程和进程间通信、进程边界
Windows API笔记(三)线程和线程同步、线程局部存储
Windows API笔记(四)win32内存结构
Windows API笔记(五)虚拟内存
Windows API笔记(六)内存映射文件
Windows API笔记(七)堆
Windows API笔记(八)文件系统
Windows API笔记(九)窗口消息
Windows API笔记(十)动态链接库
Windows API笔记(十一)设备I/O



进程常被定义为应用程序的一个运行实例。在Win32中,每个进程拥有4GB的地址空间。进程是惰性的,Win32进程什么也不执行,它只是拥有4GB的地址空间来存放应用程序所需的二进制代码和数据。

除地址空间外,每个程序还拥有别的资源,比如文件、动态内存分配和线程。这些不同的资源在进程的生命中被创建,当进程终止时,它们也被释放。

每个线程有自己的CPU寄存器组和栈。操作系统为每个独立的线程进行CPU的时间调度,操作系统以轮转方式向线程提供时间片。

1. Win32 应用程序

系统的加载器关心应用程序是基于CUI还是GUI,如果exe文件中指出是基于CUI的应用程序,加载器会自动为该程序生成一个控制台窗口。

1.1 进程的句柄

每个加载进进程地址空间的exe或dll文件都有一个唯一的实例句柄。exe文件的实例是作为WinMain的第一个参数hinstExe传递的,在调用装入资源的函数时通常需要该句柄的值。

1.2 进程的环境变量

每个进程都有相关联的环境块。环境块是分配在进程的地址空间中的一块内存。
一般子进程从它的父进程那里继承了一组完全一样的环境变量。不过父进程可以控制子进程继承哪些变量(通过CreateProcess的参数设置)。
可通过GetEnvironmentVariable和SetEnvironmentVariable获取及设置环境变量。

1.3 进程的错误模式

每个进程都有一组标志来告诉系统该怎样对严重的错误做出反应,进程可以调用SetErrorMode函数该告诉系统如何处理每种错误:

标志描述
SEM_FAILCRITICALERRORS0x0001系统不显示严重错误处理消息框,把错误返回调用的进程
SEM_NOGPFAULTERRORBOX0x0002系统不显示普通保护错误消息框,该标志只能被调试应用程序设置来用异常句柄自己处理普通保护(GP)错误
SEM_NOALIGNMENTFAULTEXCEPT0x0004系统在找不到文件时不现实消息框
SEM_NOOPENFILEERRORBOX0x8000系统自动修正内存排序错误,使它们对应用不可见,该标志对x86或Alpha处理器没有作用

缺省情况,子进程会继承父进程的错误模式。也可以在CreateProcess使设置不继承。

1.4 进程的当前驱动器和目录

可在环境变量中设置

1.5 系统版本

// 这个有点坑,程序员把主次版本颠倒了
DWORD GetVersion(void)

// 用这个
BOOL GetVersionEx(LPOSVERSIONINFOA lpVersionInformation);
	
    printf("%X \n", GetVersion());

    OSVERSIONINFO osv;
    osv.dwOSVersionInfoSize = sizeof(osv);

    BOOL ret = GetVersionEx(&osv);
    if (ret)
    {
        printf("%X - %X - %X - %X - %s\n",
               osv.dwMajorVersion,	// 主版本
               osv.dwMinorVersion,	// 此版本
               osv.dwBuildNumber,	// 编译序号
               osv.dwPlatformId,			//
               osv.szCSDVersion);
    }
    else
    {
        perror("GetVersionEx Error");
    }

2. CreateProcess函数

BOOL CreateProcess(
    _In_opt_ LPCSTR lpApplicationName,
    _Inout_opt_ LPSTR lpCommandLine,
    _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes,
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
    _In_ BOOL bInheritHandles,
    _In_ DWORD dwCreationFlags,
    _In_opt_ LPVOID lpEnvironment,
    _In_opt_ LPCSTR lpCurrentDirectory,
    _In_ LPSTARTUPINFOA lpStartupInfo,
    _Out_ LPPROCESS_INFORMATION lpProcessInformation
    );

3. 终止进程

  1. 进程中某个线程调用了ExitProcess函数
  2. 进程中某个线程调用了TerminateProcess函数(可以终结当前进程,也可以杀死其他进程)

在主线程中使用return和ExitProcess及TerminateProcess有什么不同?参考:《Windows下return,exit和ExitProcess的区别和分析- -

进程中的所有线程结束(ExitThread、TerminateThread)后会自动终止进程。

进程结束时,发生了什么:

  • 余下所有线程都被终止
  • 进程分配的内存被释放(线程分配的可能没有被释放),所有内核对象被关闭
  • 进程内核对象状态变成了有信号态(WaitForSingleObject将会得到返回值)
  • 进程的退出码从STILL、ACTIVE变成了由ExitProcess或TerminateProcess传递的代码
  • 进程内核对象的使用计数被-1(进程内核对象不一定会变成0,需要所有引用进程调用CloseHandle或者进程关闭,或者调用GetExitCodeProcess)

4. 子进程

创建一个新线程,并等待结果:

        STARTUPINFO si;
        memset(&si, 0, sizeof(STARTUPINFO)); //初始化si在内存块中的值
        si.cb = sizeof(STARTUPINFO);
        si.dwFlags = STARTF_USESHOWWINDOW;
        si.wShowWindow = TRUE;

        PROCESS_INFORMATION pi;
        ZeroMemory(&pi, sizeof(pi));

		DWORD dwExitCode;

        char exec_file[] = TEXT("kernel_handle_inherit.exe"); //

        if (!CreateProcess(exec_file, //执行模块
                           cmd,       //命令行参数
                           NULL,
                           NULL,
                           TRUE,               //继承父进程的句柄表
                           CREATE_NEW_CONSOLE, // 为新进程创建一个新的控制台窗口
                           NULL,
                           NULL,
                           &si,
                           &pi))
        {
            perror("CreateProcess Error");
            exit(1);
        }
        else
        {
        	//尽早关闭子进程的主线程
            ::CloseHandle(pi.hThread);
            
            // 等待子进程结束
            WaitForSingleObject(pi.hProcess, INFINITE);
            
            // 获取退出码
            GetExitCodeProcess(pi.hProcess,&dwExitCode);
            
            // 关闭子进程,使用计数-1,系统释放进程内核对象
            ::CloseHandle(pi.hProcess);
        }

4.1 运行分离的子进程

不等待子进程关闭:

		PROCESS_INFORMATION pi;
        if (!CreateProcess(,,,&pi))
        {
            perror("CreateProcess Error");
            exit(1);
        }
        else
        {
        	//尽早关闭子进程的主线程
            ::CloseHandle(pi.hThread);
            // 关闭子进程,使用计数-1,不影响系统释放进程内核对象(否则将产生僵尸进程)
            ::CloseHandle(pi.hProcess);
        }

5. 进程间通信

Interprocess Communications

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值