0x01.什么是线程?
1、线程是附属在进程上的执行实体,是代码的执行流程
进程 本身是空间上的概念,代表4GB的虚拟内存,线程代表着时间概念,也就是说,线程是当前运行的代码
在某个时间点只能有一段代码执行,但是cpu切换的快,所以看着像同时运行,这是单核的,所以单核的情况下并不是真正的多线程
因为线程执行的话是需要一套寄存器的,比如eax,ecx,ebx...
2、一个进程可以保护多个线程,但一个进程至少要包含一个线程
我们现在想创建一个线程了,其实main函数这边就是一个线程了,但是我们需要再创建一个呢?
需要使用到新的api,CreateThread
0x02. 创建线程
CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //安全描述符,判断子进程是否可以继续父进程的句柄表,NULL就可以了
IZE_T dwStackSize, //初始堆栈,如果不填写就会自动填写默认的
LPTHREAD_START_ROUTINE lpStartAddress, //当前的线程要执行的代码
__drv_aliasesMem LPVOID lpParameter, //要创建的线程的参数,这是个指针
DWORD dwCreationFlags, //创建线程的标识
LPDWORD lpThreadId //这个是OUT类型参数,这个参数说明是往外传递结果的,这个就是返回创建的线程ID,返回值是当前线程的句柄
);
dwCreationFlags标识:
由于是返回值是句柄,所以我们要声明一个句柄变量进行接收,也可以不接收
CloseHandle()
不想用的话可以用这个函数关闭,但是这里的关闭其实是减掉一个计数器
线程的内核对象计数器为0也不会关闭,关闭线程的两个必要条件
①、线程的内核对象计数器为 0
②、线程的执行代码执行完毕了
#include <stdio.h>
#include <windows.h>
int main()
{
HANDLE hThread = CreateThread(NULL, 0, 0, NULL, 0, NULL);
CloseHandle(hThread);
for (int i = 0; i < 100; i++)
{
Sleep(500);
printf("------- %d --------
", i);
}
getchar();
return 0;
}
所以我们这边CloseHandle
掉线程也是没有影响的,并不会影响到线程,因为当前代码没执行完后是没有人能关掉的
然后看向CreateThread的第三个参数:lpStartAddress
而这个参数是要执行的代码,然而这个代码是不能随便乱写的,是有格式的
#include <stdio.h>
#include <windows.h>
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
return 0;
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, 0, NULL, 0, NULL);
CloseHandle(hThread);
for (int i = 0; i < 100; i++)
{
Sleep(500);
printf("------- %d --------
", i);
}
getchar();
return 0;
}
然后我们在这个ThreadProc
函数中写上代码,我们依然写入for循环来
然后基本就类似是同时运行的,所以以后每创建一个线程就必须要使用 CreateThread函数来
这个函数就是告诉代码在哪里,返回值啥的就需要强转就可以了
这时候我们想指定线程循环的次数呢?
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
int* p = (int*)lpParameter;
for (int i = 0; i < *p; i++)
{
Sleep(500);
printf("++++++++++++++ %d
", i);
}
return 0;
}
在ThreadProc() 函数内小改动一下,main函数中指定一下要几次
int main()
{
int n;
n = 10;
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (LPVOID)&n, 0, NULL);
CloseHandle(hThread);
for (int i = 0; i < 100; i++)
{
Sleep(500);
printf("------- %d
", i);
}
getchar();
return 0;
}
线程参数可以传任何参数,传进去后转型一下就好了,然后运行一下,发现成功了