Windows内核之线程启动的背后

本文深入探讨Windows内核中线程的启动过程,从CreateThread函数的调用来讲解线程内核对象的创建、堆栈分配、线程执行的开始以及C/C++运行时的交互。内容涵盖线程内核对象的初始化、RtlUserThreadStart函数的调用、运行时全局变量的管理以及线程句柄和ID的使用。文章还提醒了在使用线程时应注意的C/C++运行时库事项,避免潜在的问题和资源泄漏。
摘要由CSDN通过智能技术生成

1       CreateThread函数调用后发生事情:

1.1:创建一个系统内核对象,并且初始化系统内核对象

线程的内核对象包括:context(设备上下文),使用计数,暂停计数,退出代码,已通知。

使用计数 = 2;暂停计数 = 1;退出代码 = STILL_ACTIVE;已通知=FALSE;上下文之SP(堆栈指针)= 线程的入口函数地址,上下文之IP= BaseThreadStart,线程内核对象如下图所示:


1.2 在进程的地址空间上分配用于线程堆栈的内存

传入堆栈的第1个参数是CreateThread函数的lpParameter,第2个参数是lpStartAddress。

 

1.3 检查CREATESUSPENDED是否传递给CreateThread函数,如果没有,那么暂停计数变为0,

 

2       线程的开始执行

         线程的内核对象以及堆栈初始化完成以后,操作系统调用VOID RtlUserThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOIDpvParam)函数来执行新的线程函数。这个函数的原型如下所示:

VOID RtlUserThreadStart(PTHREAD_START_ROUTINE pfnStartAddr, PVOID pvParam) {
__try {
ExitThread((pfnStartAddr)(pvParam));
}
__except(UnhandledExceptionFilter(GetExceptionInformation())) {
ExitProcess(GetExceptionCode());
}
// NOTE: We never get here.
}

这个函数不是由别的函数来调用的,而是操作系统调用的,函数的两个参数也是由操作系统压入现成的栈内的。函数的调用方式是_cdel,这是C/C++函数调用的默认方式。不过这次的调用者不是操作系统而是函数。执行RtlUserThreadStart函数时候发生的事情:

<1>在线程函数处建立SHE帧,负责运行库相关的事情。

<2>系统调用线程函数,把lpParam传递给线程函数

<3>线程函数返回时,调用ExitThread函数,线程内核计数减1

<4>如果线程产生一个没有处理的异常,那么SEH帧将处理该异常条件。通常,这意味着一个消息框呈现给用户,当用户撤销消息框时,RtlUserThreadStart函数调用ExitProcess来终结整个进程。

3      C/C++ 运行时

在早些时候,VC++ 有6个C/C++运行库,其中有两个是属于单线程的,但是现在已经没有了专门属于单线程的运行库。现在的6个运行时库如下所示:


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值