1.         进程是执行文件的运行时形态。包括两部分:内核数据(对应内核对象)、地址空间(包括执行文件代码和栈堆等动态内存)。

2.         把VC的“系统-子系统”值删除掉,即不指定控制台或GUI,则编译器会根据代码中存在main或者WinMain来自动选择子系统(这里不谈Unicode了),很方便。

3.         启动程序:根据子系统执行mainCRTStartup/WinMainCRTStartup,在该函数中干几件事(1)准备命令行和环境变量(用于char *argv[]和char *env[])(2)初始化CRT的全局变量(包括_osver、_winmajor、_winver、__argc、_environ等)(3)初始化CRT运行库的内存分配(malloc、free)、IO函数等(4)初始化全局对象调用C++构造函数。

4.         退出程序:main返回后mainCRTStartup会调用exit,exit干以下几件事:(1)执行通过_onexit注册的函数(2)执行全局对象的C++析构函数(通过atexit注册的)(3)判断_CrtDumpMemoryLeaks设置的内存泄漏检测标志,尝试检测内存泄漏(4)调用ExitProcess。

5.         HINSTANCE和HMOUDLE完全相同,都是表示映像文件加载到内存后的基址(链接器中可以配置)。GetModuleHandle传入文件名可以获得模块基址;传入NULL可以得到执行文件的HINSTANCE(即使调用者位于某个模块中同样返回应用程序基址);GetModuleHandleEx可以根据函数地址得到模块基址

6.         访问环境变量:char *env[]参数、GetEnvironmentStrings、GetEnvironmentVariable、ExpandEnvironmentStrings(将一个使用了类似”%USERPROFILE%”环境变量的字符串中的变量替换成值)。

7.         系统环境变量:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Enviroment。用户环境变量:HKEY_CURRENT_USER\Enviroment。

8.         修改环境变量后可以通知相关的系统窗口(如控制面板等):SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) “Enviroment”)。

9.         可以设置特定线程在一个CPU核心集合上执行。

10.     SetErrorMode。设置该进程如何响应各种错误。

11.     关于相对路径:在通过GetEnvironmentStrings返回的环境变量中,有一部分不是真正的环境变量,比如“=C:=C:\Windows”“ =F:=F:\Projects\Test05”,他们表示一种进程相关配置“本进程在特定驱动器下对应的当前文件夹”。一个进程除了有以上配置外,还有一个当前驱动器,最终GetCurrentDirectory返回的当前路径就是当前驱动器+当前驱动器对应的当前文件夹。使用SetCurrentDirectory会改变该驱动器的当前文件夹,还会改变进程的当前驱动器(但这个API的改变并不会在GetEnvironmentStrings上体现出来,使用C函数_chdir可以同时改变两者,故C函数更优)。进程刚启动时,如果不考虑从父进程继承的环境,则只有进程当前驱动有当前文件夹,其他驱动都无配置。使用相对路径访问文件的时候,其绝对路径可以用GetFullPathName得到。”文件名”这样的相对路径的绝对路径是GetCurrentDirectory() + “文件名”;”驱动器盘符:文件名”(注意不是”驱动符:/文件名”)这样的相对路径的绝对路径就是”该驱动器的当前文件夹”(如果无配置,则是根目录) + “文件名”。

看如下代码:

_chdir("D:/Downloads"); // 修改D:的当前路径为Downloads,且进程当前驱动器为D:

_chdir("F:/Projects"); // 修改F:的当前路径为Projects,且进程当前驱动器为F:

std::ofstream("1.txt"); // 当前驱动器是F:,所以绝对路径是F:/Projects/1.txt

std::ofstream("d:1.txt"); // D:的当前路径是Downloads,所以绝对路径是D:/Downloads/1.txt

这种行为从cmd的cd命令也可以看得出点端倪。

归纳:相对路径访问文件的时候,首先将相对路径展开成绝对路径,使用GetFullPathName,后者分两步:首先判断是否包含驱动器(以X:开头),如果没有,则在开头添加进程当前驱动器;然后检查是否以”X:/”开头,如果没有,则将”X:”展开成”X:/” + “对应驱动的当前文件夹”。两步过后得到绝对路径。

12.     GetVersionEx获取系统版本信息。VerifyVersionInfo检测当前系统是否满足版本需要。

13.     CreateProcess的参数:关于lpApplicationName和lpCommandLine,有两种用法:(1)前者指定应用程序路径,后者指定参数(第一个参数前面要有一个空格,似乎底层会直接连接两个串)(2)前者为NULL,后者指定路径和参数,空格隔开。常用第二种方法。注意,lpCommandLine中由于是用空格分隔参数的,所以对其中含有空格的路径一定要用内层引号括起来。另外CreateProcessW有一个奇怪的行为,它会修改参数lpCommandLine(似乎只在lpApplicationName为空的时候会修改),所以使用Unicode版本的时候传入的该参数不能是常字符串(如L”Nodepad 1.txt”),而应该另外准备缓冲传给该API供其修改,因为ANSI版本是调用Unicode版本的且在编码转换的时候内置了缓冲,所以CreateProcessA的lpCommandLine参数可以是常串(最终API会修改转换编码的临时缓冲)。默认情况下,CUI的CUI型子进程会和父进程共享控制台,在参数dwCreationFlags中添加DETACHED_PROCESS或CREATE_NEW_CONSOLE标志可以阻止这种行为。在dwCreationFlags中添加CREATE_NEW_PROCESS_GROUP标志,可以控制进程组的组织,用户按下Ctrl+C的时候同一进程组的所有进程得到通知。lpEnvironment指定为NULL的时候,底层为用GetEnvironmentStrings来填充。lpCurrentDirectory为NULL的时候,子进程继承父进程的当前目录。lpStartupInfo不能为空,至少要初始化结构为0并将cb赋为sizeof。使用STARTUPINFOEX结构作为lpStartupInfo参数,还可以具体指定子进程要继承哪些父进程的可继承内核对象(即使bInheritHandles参数为FALSE)。

14.     cmd进程输入命令行前显示的路径,就是其当前路径(GetCurrentDirectory)。在CreateProcess时,cmd没有设置子进程当前路径,而资源管理器将路径设置成子进程镜像目录。因为cmd的子进程会继承cmd的当前路径(lpCurrentDirectory为空的结果),因此最好在用cmd启动程序的时候先将cmd的当前路径设置为新进程的镜像路径。

15.     进程和线程结束后,句柄对象被标记为激活, WaitForSingleObject会返回。

16.     CreateProcess后,可以使用WaitForInputIdle或类似函数来等待新进程初始化环境完毕开始运行。

17.     WoW64:Windows 32 On Windows 64。所有64位windows运行着这个虚拟机,用来执行32位程序。判断一个32位程序是否是运行在64位系统的32位虚拟机中:IsWow64Process。

18.     父进程创建子进程时使用的lpStartupInfo,在子进程中可以使用GetStartupInfo来查询。

19.     创建一个子进程时,进程和主线程本身的存在就有了引用1,而调用CreateProcess的父进程又会有他们的引用所以计数到了2。要完全销毁进程和线程,需要计数为0,所以除了需要进程本身结束外,引用的该进程的其他线程也要释放引用。当然,CreateProcess过后父进程马上CloseHandle并不会结束子进程,只是释放自己的引用,使其计数为1,这是正常的行为。要确保某个进程或线程不被销毁,不调用CloseHandle即可。如果进程本身已经退出了,但还有其他进程引用它,则它的地址空间被回收,只有内核对象还存在(比如这时再对句柄使用API查看内存,则内存信息为空),这也是为什么可以查看已经退出的进程的退出码的原因(退出码保存在内核对象中)。

20.     进程和线程的ID位于同一个系统顶层名空间。即任意进程的任意线程ID绝不可能和任意进程ID相同。这个ID会被系统循环利用。

21.     GetProcessIDOfThread。

22.     进程只有在它所有线程都结束后才会结束。ExitProcess会杀死所有线程,所以可以直接结束进程,在主线程中调用ExitThread只会结束主线程(即,主线程创建一个死循环线程后自己_exitthreadex,这个进程不会退出。)。main返回后CRT调用exit后者再调用ExitProcess,所以在main中return可以直接结束进程。

23.     通过ExitProcess或ExitThread(单线程时)结束进程,由于这些API比CRT更底层,他们只能保证正确的释放Windows资源(内存、内核对象引用),并不保证释放C++资源(CRT底层资源、全局对象的析构函数),故一定要从main中返回自然的结束进程(其他原因在后面章节说明)。TerminateProcess也出于相同的原因应该避免使用。

24.     CreateProcess创建的子进程会继承父进程的Security Token权限,而ShellExecuteEx可以提高子进程的权限(令lpVerb参数为”runas”)。资源管理器使用前者创建子进程,所以通过它开打的程序都具有和资源管理器相同的权限。

25.     关于Vista及更高系统的UAC(User Account Control):Vista以前的系统如果以管理员账号登陆,资源管理器(Explorer)会获得一个管理员权限的Security Token,然后从资源管理器打开的子进程都会继承这个最高权限,这种行为非常危险。Vista以后,即使以管理员账号登陆,资源管理器仍然只持有一个一般权限的Token(Filtered Token),子进程如果想提升权限,有两种途径:(1)用户“以管理员身份运行”启动该进程(2)子进程自己提出请求要求用户提升权限(子进程是安装程序、或者子进程配置有.manifest文件说明权限需求)。另外,在很多软件中出现有小盾牌图标的按钮,也是要求提高权限,点击过后会结束当前进程,重启一个高权限进程(如资源管理器中“显示所有用户的进程”按钮)。其实这三种提高权限都是父进程调用了ShellExecuteEx。

26.     IsUserAnAdmin判断当前用户是否是管理员。在Vista及以上的系统中,即使是管理员,进程也有可能因为筛选Token而不具备最高权限。

27.     枚举所有进程:Process32First、Process32Next、EnumProcesses。

28.     可以从HMOUDLE中读取IMAGE_DOS_HEADER和IMAGE_NT_HEADERS,进而从这些PE头中取得模块的推荐加载地址等信息。

29.     PEB(Process Enviroment Block)包含了进程的启动命令行、当前路径等数据。该字段可以通过NtQueryInformationProcess的PROCESS_BASIC_INFORMATION参数取得。

30.     可以通过WinDbg的dt命令,查看一些结构的具体成员布局,如PEB等。

31.     Windows完整性机制(Windows Integrity Mechanism):这是UAC之外的另一套安全机制,Windows通过在系统访问控制表(SACL, System Access Control List)中增加访问控制项(ACE, Access Control Entry)实现,每一种受保护的资源都有对应的完整性级别(Integrity Level),每个进程都有一个基于Token计算的完整性级别,如果进程的级别小于资源的级别,则不能访问资源。提升Token权限之前的进程级别为中,提升后为高,而像IE这样可以能执行网络代码的进程为低。可以通过GetTokenInfomation查看一些和完整性级别相关的策略。窗口系统也根据完整性级别,拒绝低级别者向高级别使用PostMessage、SendMessage等API。

32.     Vista以上有一些进程是特殊的受保护进程,ToolHelp API对他们无效,因此无法查看进程信息。

33.     GetProcessTime查看进程时间,GetProcessIoCounters查看IO次数

34.     GetProcessImageFileName返回内核格式的文件名

http://blog.csdn.net/biggbang/article/details/24390241

《解读window核心编程》 之 进程的更多相关文章

  1. 《解读window核心编程》 之 字符和字符串处理方式

    推荐的字符和字符串处理方式 開始将文本字符串想象为字符的数组,而不是 char 或字节的数组. 用通用数据类型(如 TCHAR/PTSTR )来表示文本字符和字符串. 用明白的数据类型(如 BYTE  ...

  2. 《解读window核心编程》 之 注冊表

    1 注冊表的作用及组织形式 Windows系统使用注冊表来存储系统和应用程序配置数据.非常多系统和应用程序重要的配置的信息都存储在注冊表中. 注冊表是一种以树型结构组织的数据库.树的每个节点称 作键( ...

  3. windows核心编程之进程间共享数据

    有时候我们会遇到window进程间共享数据的需求,例如说我想知道系统当前有多少某个进程的实例. 我们能够在程序中定义一个全局变量.初始化为0.每当程序启动后就加1.当然我们我们能够借助第三方介质来储存 ...

  4. windows核心编程-信号量(semaphore)

    线程同步的方式主要有:临界区.互斥区.事件.信号量四种方式. 前边讲过了互斥器线程同步-----windows核心编程-互斥器(Mutexes),这章我来介绍一下信号量(semaphore)线程同步. ...

  5. Windows核心编程:第4章 进程

    Github https://github.com/gongluck/Windows-Core-Program.git //第4章 进程.cpp: 定义应用程序的入口点. // #include &q ...

  6. 回忆读windows 核心编程

    看<windows 核心编程> 第五版到纤程了,下一章节即将介绍内存体系编程.如果做window平台下的开发,我感觉此书一定要读.记得开始讲解了window的基础,然后讲解内核对象.内核对 ...

  7. 【windows核心编程】 第六章 线程基础

    Windows核心编程 第六章 线程基础 欢迎转载 转载请注明出处:http://www.cnblogs.com/cuish/p/3145214.html 1. 线程的组成 ①    一个是线程的内核 ...

  8. python核心编程第二版笔记

    python核心编程第二版笔记由网友提供:open168 python核心编程--笔记(很详细,建议收藏) 解释器options:1.1 –d   提供调试输出1.2 –O   生成优化的字节码(生成 ...

  9. python核心编程--笔记

    python核心编程--笔记 的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找pyt ...

随机推荐

  1. Java Service Wrapper 使用(windows)

    1       简介 最近项目中需要做一个Windows系统服务,记录一下使用过程. Java Service Wrapper 可以将Java程序包装成系统服务,这样就可以随着系统的运行而自动运行.J ...

  2. CAP和最终一致性

    查阅资料整理了最终一致性.CAP 相关的内容.由于图省事儿,没有做文字的整理记载,只有 slides 和一些查阅过的链接,大家将就着看.欢迎指正. slides: slides 链接:请戳这里 背景 ...

  3. 设置npm淘宝镜像

    npm config set registry https://registry.npm.taobao.org

  4. mod_timer函数及其他定时器函数

    当一个定时器已经被插入到内核动态定时器链表中后,我们还能够改动该定时器的expires值.函数mod_timer()实现这一点 改动注冊入计时器列表的handler的起动时间 int mod_time ...

  5. js小贴士

    1.在js中 定义方法 方法名第一个字母小写.如果是定义类 则第一个字母大学 2.如果想在a标签中点击 触发js方法 而不跳转页面 可以使用类似   <a href="javascri ...

  6. WPF扑克牌之红桃K

    原文:WPF扑克牌之红桃K 有些什么用途呢?我想,如果你有兴趣,可用来制作WPF扑克牌游戏. 没有任何技术含量,需要做的是在Blend中绘图或者使用Illustrator,CoreDraw等矢图设计软 ...

  7. 第1讲:The nature of Testing--測试的本质

    *********声明:本系列课程为Cem Kanner的软件黑盒測试基础的笔记版************** What's A COMPUTER PROGRAM? Textbooks often d ...

  8. 《TIME》时代周刊阅读

    0. 常识 tribunal 是解决民事诉讼和民事纠纷的地方,以调解为主,使用主席制.主席是受过司法培训,具有一定法律基础的,但不能像法官一样直接给你判决,也不能强制执行. Court 一般针对严重案 ...

  9. Leetcode 260 Single Number III 亦或

    在一个数组中找出两个不同的仅出现一次的数(其他数字出现两次) 同样用亦或来解决(参考编程之美的1.5) 先去取出总亦或值 然后分类,在最后一位出现1的数位上分类成 ans[0]和ans[1] a&am ...

  10. Codeforces Round #248 (Div. 2) B称号 【数据结构:树状数组】

    主题链接:http://codeforces.com/contest/433/problem/B 题目大意:给n(1 ≤ n ≤ 105)个数据(1 ≤ vi ≤ 109),当中有m(1 ≤ m ≤  ...