然后,看一下我们可能需要的一些API第一个CreateProcess
这个函数很恶心啊,先看看他的声明(M$的东西一贯恶心,习惯就好)
- BOOL WINAPI CreateProcess(
- __in_opt LPCTSTR lpApplicationName,
- __inout_opt LPTSTR lpCommandLine,
- __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
- __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
- __in BOOL bInheritHandles,
- __in DWORD dwCreationFlags,
- __in_opt LPVOID lpEnvironment,
- __in_opt LPCTSTR lpCurrentDirectory,
- __in LPSTARTUPINFO lpStartupInfo,
- __out LPPROCESS_INFORMATION lpProcessInformation
- );
复制代码对参数,不做太详细的解释,这里只对这个函数做一点简单说明lpApplicationName 进程名
lpCommandLine 进程路径+进程名
lpProcessAttributes 进程安全描述结构
lpThreadAttributes 线程安全描述结构
bInheritHandles 是否从父进程继承句柄
dwCreateFlags 进程优先级等等,看文档比较靠谱,参数比较复杂
lpEnvironment 进程的环境变量(不指定的话,默认继承父进程的所有环境变量)
lpStartupInfo 进程创建以后的状态(挂起,就绪...),这里能设置的和dwCreateFlags其实有类似的地方,具体不做太多讨论,看文档比较靠谱
lpCurrentDirectory 进程创建以后的路径,默认是可执行文件exe的路径
lpProcessInformation 返回的进程信息,包含进程句柄和线程句柄
接下来,就是用这玩意创建一个进程了。(想想linux和unix下的fork函数吧,多么简单,或者是exec函数...)
再下来,需要简单介绍下CreateThread,因为上文里说了,需要一个不影响当前进程执行的模块来负责做守护
那么,CreateThread又有啥呢?当然,CreateThread函数就相对简单的多了
- HANDLE WINAPI CreateThread(
- __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
- __in SIZE_T dwStackSize,
- __in LPTHREAD_START_ROUTINE lpStartAddress,
- __in_opt LPVOID lpParameter,
- __in DWORD dwCreationFlags,
- __out_opt LPDWORD lpThreadId
- );
复制代码lpThreadAttributes 线程安全结构dwStackSize 线程栈大小
lpStartAddress 线程执行体函数
lpParameter 线程执行体函数的参数
dwCreateFlags 线程的优先级,线程状态等标志
lpThreadId 线程ID
参数确实相比进程简单了很多,但是还是复杂
如此复杂的API,如何调用?这确实是问题,不过好处是,对于绝大部分的情况,我们都可以传NULL(对于非指针和句柄传0代替)
API内部看到NULL(0)以后会用默认的参数来代替他们
那么,我们可以如何调用呢?
下面写2个简单的调用例子
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
- ZeroMemory(&pi, sizeof(pi));
复制代码以上就是创建一个进程的代码了,如果不出特殊需求
创建进程都可以用这种形式,对我们不关注的参数,直接传NULL 或者是 0
那么,线程呢?
线程可能有点麻烦的
现在的线程创建,一般是把一个函数当作一个线程来执行
所以,我们首先需要定义一个函数,作为线程的执行体。
和进程的入口函数main(其实main不是真正的入口,以后讲到PE文件的时候会讲到),线程的入口函数也是一个固定的格式
DWORD WINAPI ThreadProc(void *arg);
只有满足这个格式的函数才能当作线程函数
这里的函数声明又多了一个东西,叫做WINAPI
其实WINAPI是个宏,在windows.h里面是这样定义的
#define WINAPI __stdcall
他规定了函数的调用约定方式(这个涉及到一点点的汇编知识,所以就暂时不展开讲了),平时用的最多的C库,调用约定都是__cdecl的形式
好了,废话说完了,那么,如何创建一个线程呢?
- DWORD WINAPI ThreadProc(void *arg)
- {
- return 0;
- }
- HANDLE hThread;
- DWORD dwThreadID;
- hThread = CreateThread(
- NULL,
- 0,
- MyThreadFunction,
- pDataArray[i],
- 0,
- &dwThreadID
- );
复制代码如此,就能创建一个线程了