进程与线程
没有线程的进程是没有意义的,会被关闭
进程是死的,它要活着,必须是有一个或多个的线程存在
进程是一块空间,存在于内存中,里面包含有许多的代码,也可以把它看做是一个清单,线程负责执行的就是清单上面的内容,如果进程内没有线程,那么进程内的代码也就没法执行了。
所以当系统创建一个进程时, 会自动创建第一个线程, 这个线程我们称为主线程
线程是由CPU来管控的(进程由内存管控),二者是分开的两部分
单核下,多线程和单线程执行是一样的,因为此时的多线程只是一个“假”的多线程。但是有些不一样:空间不一样,切换成本不一样
切换线程上下文与切换进程上下文
切换进程上下文
需要先保存当前进程状态:把空间copy到磁盘缓存,再把当前进程所占空间从物理内存中卸下,毕竟物理内存是有限的…
切换线程上下文
只需保存线程状态而不保存进程状态
明显线程更省资源,就像大型游戏切换到桌面的时候,会有卡顿,就是因为切换了进程
一个进程可以拥有多个线程
所有的线程都能在进程的地址空间中”同时”运行代码,每个线程都有它自己的一组CPU寄存器和自己的堆栈
内核对象
操作系统用来管理进程
地址空间
包含了可执行文件及DLL模块的代码和数据
CUI及GUI
CUI
基于文本操作,控制台界面
入口函数:main
GUI
基于图形界面,使用鼠标操作
入口函数:WinMain
改变入口函数,会报错,CUI和GUI的呈现方式不同,其它的都是差不多的,都是一个程序。写的是GUI程序,但是同样可以新建或附加一个控制台程序。它们在编译的时候会有所区别(比如VS2015中的项目属性中的链接器中的系统中的子系统可以看到区别),根据这个区别,编译器在编译的时候会去找相对应的入口函数。
如果不设置,main和WinMain都可以,编译器会进行自动进行推导
当设置好了,编译器会将设置的这个值写入生成文件的头部,当操作系统运行这个文件的时候,会检查这个位,然后使用相应的方式进行程序
命令提示符(cmd.exe),是一个软件(独立的),需要执行的软件是另一个软件,windows会使用命令提示符来运行这个软件,然后程序自命令提示符。我们执行的这个软件其实并没有一个独立的界面,只是依附于命令提示符
总结:GUI和CUI的异同
相同都是一个程序
不同
入口函数不同
启动方式不同(在逆向的时候需要知道(找入口点))wimmainCRTStartup或mainCRTStartup,这是编译器在链接的时候做的事情
链接器中的设置不同(文件的头部不同)
WinMian函数原型
原型
int _stdcall _tWinMain(
HINSTANCE hInstance, //进程句柄
HINSTANCE hPrevInstance, //前一个进程的句柄,一般都不要去使用它
LPTSTR lpCmdLine, //命令行
int nCmdShow //显示方式 SW_SHOW SW_HIDE
){}
进程句柄
是一个内核对象
加载到进程地址空间的每一个执行体或者DLL文件都被赋予了一个独一无二的实例句柄
GetModuleHandle(nullptr)
拿到当前的实例句柄
可以这样认为:HMODULE与HINSTANCE是一样的….
拿到的是基地址,默认的是0x400000,将VS2015中的链接器->高级->随机基址设置为否,则每次运行程序的基地址都是一样的,是程序的入口(exe的起始)
同时运行多个程序,都是0x400000,这不冲突,因为每个进程都是独立的进程空间,也就是说,每次启动一个进程,都是有0x400000
总而言之,句柄(HINSTANCE)代表的就是这个基地址
命令行参数
是程序和外界的一个交互
>
获取cmdlineGetCommandLine
返回值:LPTSTR*
返回的是一个指针,说明这块空间是一直存在的,而且我们不能去更改,一旦我们更改了,全局的都会出现反应,所以一般会使用const进行修饰
CommandLineToArgvW(strCommandLine,&nNumArgv)
返回值:指针的指针 LPWSTR*,存储的是传入的命令行参数,每个命令行之间使用空格分隔
这个需要使用LocalFree进行释放
环境变量
相当于系统中全局的cmd,它经常用于一些指标,放了一些系统指定的东西
比如软件放在哪个路径下
GetEnvironmentStrings
获取环境变量
FreeEnvironmentStrings
释放环境变量
GetEnvironmentVariable
查看某一环境变量是否存在
进程路径
进程所在目录
指的是当前运行程序(exe)所在的目录
比如说,调试状态与直接运行exe的所在目录是不一样的
获取所在目录
GetCurrentDirectory
设置所在目录
SetCurrentDirectory
进程当前目录
针对的是盘符:C、D、E…
Module所在目录
当前可执行程序文件的目录+文件名