0x00 前言
文章中的文字可能存在语法错误以及标点错误,请谅解;
如果在文章中发现代码错误或其它问题请告知,感谢!
本例运行系统环境为windows 10,使用VS2010编译运行。
0x01线程创建
主进程在运行的过程中会创建新的线程,同一个进程中运行多线程的好处是可以共享一些该进程的句柄以及全局变量等资源,当然各线程也会有自己的一些私有堆栈来保存自己的私有数据。
若想要在进程或主线程中创建一个新线程,需要指定一个进入点函数,这个函数即为线程函数,该函数定义如下:
1.函数原型及参数说明
HANDLE CreateThread(
LPSECURITY_ATRIBUTES lpThreadAttribute, //线程的安全属性
DWORD dwStackSize, //指定线程堆栈大小
LPTHREAD_START_ROUTINE lpStartAddress, //线程函数的起始地址
LPVOID lpParameter, //传递给线程函数的参数
DWORD dwCreationFlags, //指定创建后是否立即启动
DwORD *lpThreadId //用于取得内核给新生成的线程分配的线程ID
};
函数执行成功后,将返回新建线程的线程句柄。lpStarAddress参数指定了线程函数的地址,新建的线程将从此地址开始执行,直到遇到return返回结束线程执行。dwCreationFlags如果是0,表示线程创建后立刻运行,若指定Create_SUSPENDED标志,表示线程以后处于挂起状态,直到使用ResumeThread函数显示调用为止。
2.返回值
线程创建成功返回新线程的句柄,失败返回NULL
0x03代码举例
#include "StdAfx.h"
#include<stdio.h>
#include<Windows.h>
//线程函数
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
int i = 0;
while(i<20)
{
printf("I am from a thread,count=%d\n",i++);
}
return 0;
}
int main()
{
HANDLE hThread;
DWORD dwThreadId;
//创建线程
hThread = ::CreateThread(
NULL, //默认安全属性
NULL, //默认堆栈大小
ThreadProc, //线程入口地址(执行线程函数)
NULL, //传给函数参数
0, //指定线程立即运行
&dwThreadId //返回线程的ID号
);
printf("Now another thread has benn created.ID = %d\n", dwThreadId);
//等待线程结束
::WaitForSingleObject(hThread, INFINITE);
::CloseHandle(hThread);
system("pause");
return 0;
}
运行结果:
其中WaitForSingleObject()函数定义如下:
::WaitForSingleObject(
hHandle, //要等待的对象的句柄
dwMillisecond //要等待的时间(以毫秒为单位)
);
其中,WaitForSingleObject()函数用于等待指定对象hHandle变成受信状态(线程运行结束)后才返回。参数dwMillisecond给出了以毫秒为单位的要等待时间,若为INFINITE表示等待时间为无限。
0x04子进程继承线程句柄
对于一个进程的线程句柄想要被其子进程继承,就要对CreateThread()中的lpThreadAttributes和dwCreationFlags参数做设置。
首先要设置SECURITY_ATTRIBUTES结构体,将它的bInheritHandle成员初始化为TRUE
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE; //使得CreateThread返回的句柄可以被继承
//句柄h可以被子进程继承
HANDLE h = ::CreateThread(&sa,...);
另外,还需要在使用CreateProcess()创建子进程时对该函数中的bInheritHandles置为TRUE,那么子进程就可以继承父进程的可继承句柄。
以上。
参考文档:
1.张铮,孙宝山,周立天.Windows程序设计(第3版)[M].北京;人民邮电出版社,2018.7.
2.https://www.cnblogs.com/ay-a/p/8762951.html