滴水逆向——Win32_创建线程

什么是进程线程?

进程是正在运行的程序的实例。一个进程至少有一个线程,一个进程中可以并发多个线程,每条线程同时执行不同的任务

HANDLE CreateThread(
[in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
[in]            SIZE_T                  dwStackSize,		//线程堆栈大小
[in]            LPTHREAD_START_ROUTINE  lpStartAddress,		//线程的执行函数
[in, optional]  __drv_aliasesMem LPVOID lpParameter,		//线程参数
[in]            DWORD                   dwCreationFlags,	//为0则线程创建完毕后立即调度
[out, optional] LPDWORD                 lpThreadId			//线程ID
);

Tips:
1.CreateThread函数仅用于创建线程,它本身并不执行任何功能,其第三个参数才是指定线程执行函数的地址,通常为一个全局变量,而函数名称即为全局变量
2.第五个参数的值为0则在线程创建完毕后立即进行调度,但是并不代表这个线程百分百就会立即执行。因为系统总共就那么多CPU,一旦没有空余CPU,即使这个值传0,线程也不能立即执行。要等待系统分给它一个CPU,它才可以跑得动
另外,如果传入的值是CREATE_SUSPENDED,则线程创建后立即挂起,需调用ResumeThread函数后该线程方可执行

void MyTest()
{
	int num1 = 2;
	//返回值是线程句柄
	HANDLE hThread = CreateThread(
		NULL,			//安全属性,通常为NULL
		0,				//参数,用于设定线程可以将多少地址空间用于它自己的堆栈
		//每个线程都拥有它自己的堆栈
		ThreadProc,		//参数,用于指明想要新线程执行的线程函数地址
		(void*)num1,			//传入线程函数的参数
		//既可以是数字,也可以是个指向某一结构的指针
		0,				//若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
		NULL			//线程ID
	);
	::CloseHandle(hThread);
}

我们可以看到,在MyTest函数里面调用了CloseHandle来关闭线程,但是这并不代表这个线程就没了,只是把当前线程的编号(句柄)处理掉了。如果我们之后再想调用这个进程,可以通过其他函数再赋给这个线程一个句柄

但是这样的话线程还能停下吗?显然是可以的

DWORD WINAPI ThreadProc(
	LPVOID lpParameter
)
{
	int p = (int)lpParameter;
	for (int i = 0; i < 1000; i++)
	{
		Sleep(1000);
		printf("------%d-------\n",p);
	}
	return 0;
}

就拿当前程序来说,我们创建的线程调用的执行函数ThreadProc是一个循环1000次的输出,当它循环结束退出后,这个线程就跑完了

线程传参

通过上面的CreateThread函数我们知道,第四个参数就是我们想要传给线程执行函数的参数,那么怎么传参呢?一共有两种方法,一种是和上面的代码一样,用(void*)指针接收参数,再用(int*)类型进行强转;另一种就是通过全局变量进行传参:将参数声明为全局变量,然后以下列形式进行传参

DWORD WINAPI ThreadProc(
	LPVOID lpParameter
)
{
	int* p = (int*)lpParameter;
	for (int i = 0; i < 1000; i++)
	{
		Sleep(1000);
		printf("------%d-------\n",*p);
	}
	return 0;
}
int num1 = 2;
void MyTest()
{
	//返回值是线程句柄
	HANDLE hThread = CreateThread(
		NULL,			//安全属性,通常为NULL
		0,				//参数,用于设定线程可以将多少地址空间用于它自己的堆栈
		//每个线程都拥有它自己的堆栈
		ThreadProc,		//参数,用于指明想要新线程执行的线程函数地址
		(void*)&num1,			//传入线程函数的参数
		//既可以是数字,也可以是个指向某一结构的指针
		0,				//若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
		NULL			//线程ID
	);
	::CloseHandle(hThread);
}

完整代码

#include <stdio.h>
#include <Windows.h>
#include <handleapi.h>

/*
DWORD WINAPI ThreadProc(
	LPVOID lpParameter
)
{
	int p = (int)lpParameter;
	for (int i = 0; i < 1000; i++)
	{
		Sleep(1000);
		printf("------%d-------\n", p);
	}
	return 0;
}

void MyTest()
{
	int num1 = 2;
	//返回值是线程句柄
	HANDLE hThread = CreateThread(
		NULL,			//安全属性,通常为NULL
		0,				//参数,用于设定线程可以将多少地址空间用于它自己的堆栈
		//每个线程都拥有它自己的堆栈
		ThreadProc,		//参数,用于指明想要新线程执行的线程函数地址
		(void*)num1,			//传入线程函数的参数
		//既可以是数字,也可以是个指向某一结构的指针
		0,				//若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
		NULL			//线程ID
	);
	::CloseHandle(hThread);
}
*/
DWORD WINAPI ThreadProc(
	LPVOID lpParameter
)
{
	int *p = (int*)lpParameter;
	for (int i = 0; i < 1000; i++)
	{
		Sleep(1000);
		printf("------%d-------\n", *p);
	}
	return 0;
}

int num1 = 2;

void MyTest()
{
	//返回值是线程句柄
	HANDLE hThread = CreateThread(
		NULL,			//安全属性,通常为NULL
		0,				//参数,用于设定线程可以将多少地址空间用于它自己的堆栈
		//每个线程都拥有它自己的堆栈
		ThreadProc,		//参数,用于指明想要新线程执行的线程函数地址
		(void*)&num1,			//传入线程函数的参数
		//既可以是数字,也可以是个指向某一结构的指针
		0,				//若值为0,则创建后立即调度 CREATE_SUSPENDED创建后挂起
		NULL			//线程ID
	);
	::CloseHandle(hThread);
}
int main()
{
	MyTest();
	for (int i = 0; i < 1000; i++)
	{
		Sleep(1000);
		printf("+++++++++++++\n");
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值