进程线程
windows系统
windows是C和汇编写的,但是是采用的面向对象的思想写的,一个一个windows的对象本质上都是结构体变量,但是windows并不想直接暴露结构体,于是windows采用了句柄来封装一层对应的结构体,然后再用句柄对应的API来操作这些对象
在windows下分为R0内核区和R3用户区,内核区就是各种各样的windows对象(结构体),然后封装借口函数再封装到R3变成sdk,api等等给R3的User使用。
windows对象
可以大致分为三类
USER对象:窗口,控件、图标、菜单、光标 User32.dll中
GDI对象:画刷,字体,画笔 GDI32.dll中
内核对象:文件、进程、线程。 Kernel32.dll中
内核对象的创建方式
1 创建对象CreateXXXX
例:CreateProcess 创建进程 CreateThread创建线程,CreateFile创建文件,CreateSemaphore创建信号量等
2 打开对象获取句柄 OpenXXX
3 通过API来操作对象 前两步都是为了第三步用API来操作内核对象
4 关闭句柄
内核对象特性:
所有的内核对象都属于操作系统内核,可以再不同的进程间访问到,也就是说内核对象是跨进程的。
很多时候都需要在不同的进程中访问同一个内核对象,比如:进程的同步,进程共享数据等
通常,使用命名的方式在不同进程间使用内核对象
引用计数
每个内核对象都有一个引用计数,也就是说每个内核对象都有个变量来计数,统计有几个进程创建或打开了此内核对象,如果有创建和打开,该计数加一,如果某个进程终止,或者关闭了这个对象,那么计数量减1,当计数为0的时候就会销毁
安全描述符
内核对象都有一个安全描述符,这个描述符说明了谁拥有此对象,哪些用户和组被允许访问或使用此对象,以及哪些用户和组拒绝访问或使用此对象。
在创建一个内核对象的同时,需要我们传递一个安全描述符
可以通过传参是否传安全描述符来判断是否为内核对象
typedef struct _SECURITY_ATTRIBUTES { DWORD nLength;//结构体大小 LPVOID lpSecurityDescriptor;//安全描述符 BOOL bInheritHandle;//是否能被新创建的进程继承 } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
一般情况下,在创建内核对象的时候给安全描述符传NULL,就表示使用默认安全属性
windows中使用对象就要使用句柄
对于内核对象来说,内核对象的句柄和进程相关,同一个对象不同的进程中的对象句柄不同,但是需要注意的是GID对象的句柄值是全局有效的
句柄表
每个进程对象中,都有一个句柄表,用来记录该进程打开的所有内核对象
可以简单的认为句柄表就是一个一维数组,句柄值表示的是一个数组的索引值
句柄表中的每一项描述了使用此句柄访问对象的权限和是否可以被子进程继承
内核对象的跨进程访问
内核对象是全局的,所有可以在多个进程中来访问内核对象
通常有3中方式实现跨进程访问内核对象
1 父进程继承给子进程
2 使用名称或者ID作为标识来打开
3 使用DuplicateHandle函数,将句柄从一个进程传递给另一个进程
win10下的32位应用程序
操作系统会分配一个进程来处理该应用程序,该进程因为是32位的所以操作系统会给它分配一个4G的内存,该内存会分为两块,低2G的内存是用户空间,而高2G的内存是内核空间。低两G是用户进程的私有空间,而高2G则是内核空间,内核对象的特质就是所有进程共享,所以这里的空间是共享的。
什么是进程
进程是操作系统的一个重要概念,运行一个程序就会运行一个进程,进程是操作系统用来分配资源的单位。类似于一个工厂,工厂里的员工就类似于线程来处理工作
至少包含:
虚拟地址空间(也就是低2G的用户空间)
地址空间中加载的exe,还有dll
进程内核对象(在内核层中)
至少一个线程
什么是模块
包含着代码和数据的可运行文件称之为可执行文件
windows下最常见的:exe、dll文件
一个运行中的进程通常都要将好几个可执行文件加载到内存虚拟空间,每个在该进程中加载的可执行文件都称之为模块
代码实操
#include<Windows.h>
int main()
{
/*
BOOL CreateProcessA(
LPCSTR lpApplicationName, 程序路径
LPSTR lpCommandLine, 要执行的命令,如果是NULL就是表示执行命令行
LPSECURITY_ATTRIBUTES lpProcessAttributes,进程安全描述符
LPSECURITY_ATTRIBUTES lpThreadAttributes, 线程安全描述符
BOOL bInheritHandles, 是否可被继承
DWORD dwCreationFlags, 创建标识
LPVOID lpEnvironment, 指向新进程环境块指针通常为NULL
LPCSTR lpCurrentDirectory, 进程当前目录的完整路径,前面给了完整路径的画通常为NULL
LPSTARTUPINFOA lpStartupInfo, 进程启动信息
LPPROCESS_INFORMATION lpProcessInformation 进程信息
//除了进程启动信息和进程信息还有程序路径,别的基本上用默认值就好
);
*/
//这里启动路径用我写的MFC试试
LPCSTR a ="D:\\MFC\\MFC_LIST\\Debug\\MFC_LIST.exe";
STARTUPINFOA sw{ 0 };
PROCESS_INFORMATION pinfo{ 0 };
//在windows下的lp表示的是long point也就是指针类型的意思
CreateProcessA(a,NULL,NULL,NULL,FALSE,0,NULL,NULL,&sw,&pinfo);
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
return 0;
}