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的时间调度,操作系统以轮转方式向线程提供时间片。
系统的加载器关心应用程序是基于CUI还是GUI,如果exe文件中指出是基于CUI的应用程序,加载器会自动为该程序生成一个控制台窗口。
每个加载进进程地址空间的exe或dll文件都有一个唯一的实例句柄。exe文件的实例是作为WinMain的第一个参数hinstExe传递的,在调用装入资源的函数时通常需要该句柄的值。
每个进程都有相关联的环境块。环境块是分配在进程的地址空间中的一块内存。
一般子进程从它的父进程那里继承了一组完全一样的环境变量。不过父进程可以控制子进程继承哪些变量(通过CreateProcess的参数设置)。
可通过GetEnvironmentVariable和SetEnvironmentVariable获取及设置环境变量。
每个进程都有一组标志来告诉系统该怎样对严重的错误做出反应,进程可以调用SetErrorMode函数该告诉系统如何处理每种错误:
标志 | 值 | 描述 |
---|---|---|
SEM_FAILCRITICALERRORS | 0x0001 | 系统不显示严重错误处理消息框,把错误返回调用的进程 |
SEM_NOGPFAULTERRORBOX | 0x0002 | 系统不显示普通保护错误消息框,该标志只能被调试应用程序设置来用异常句柄自己处理普通保护(GP)错误 |
SEM_NOALIGNMENTFAULTEXCEPT | 0x0004 | 系统在找不到文件时不现实消息框 |
SEM_NOOPENFILEERRORBOX | 0x8000 | 系统自动修正内存排序错误,使它们对应用不可见,该标志对x86或Alpha处理器没有作用 |
缺省情况,子进程会继承父进程的错误模式。也可以在CreateProcess使设置不继承。
可在环境变量中设置
// 这个有点坑,程序员把主次版本颠倒了
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");
}
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
);
在主线程中使用return和ExitProcess及TerminateProcess有什么不同?参考:《Windows下return,exit和ExitProcess的区别和分析- -》
进程中的所有线程结束(ExitThread、TerminateThread)后会自动终止进程。
进程结束时,发生了什么:
创建一个新线程,并等待结果:
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);
}
不等待子进程关闭:
PROCESS_INFORMATION pi;
if (!CreateProcess(,,,&pi))
{
perror("CreateProcess Error");
exit(1);
}
else
{
//尽早关闭子进程的主线程
::CloseHandle(pi.hThread);
// 关闭子进程,使用计数-1,不影响系统释放进程内核对象(否则将产生僵尸进程)
::CloseHandle(pi.hProcess);
}
Interprocess Communications