《Windows核心编程系列》 -- 线程基础
作者:网络转载 发布时间:[ 2012/12/4 10:31:42 ] 推荐标签:
对于_beginthreadex函数有以下重点
1) 每个线程都有自己的专用_tiddata内存块,它们是从C/C++运行库的堆(heap)上分配的。
2)传给_beginthreadex的线程函数的地址保存在_tiddata内存块中。
3)_beginthreadex确实会在内部调用CreateThread,因为操作系统只知道用这种方式来创建一个新线程。
4)CreateThread函数被调用时,传给它的函数地址是_threadstartex(而非pfnStartAddr)。另外,参数地址是_tiddata结构的地址,而非pvParam。
5)如果一切顺利,会返回线程的句柄,像CreateThread那样。任何操作失败,会返回0。
为新线程初始化_tiddata结构之后,接着来看看这个结构如何与线程关联的:
static unsigned long WINAPI _threadstartex (void* ptd) {
// Note: ptd is the address of this thread's tiddata block.
// Associate the tiddata block with this thread so
// _getptd() will be able to find it in _callthreadstartex.
TlsSetValue(__tlsindex, ptd);
// Save this thread ID in the _tiddata block.
((_ptiddata) ptd)->_tid = GetCurrentThreadId();
// Initialize floating-point support (code not shown).
// call helper function.
_callthreadstartex ();
// We never get here; the thread dies in _callthreadstartex.
return(0L);
}
static void _callthreadstartex(void) {
_ptiddata ptd; /* pointer to thread's _tiddata struct */
// get the pointer to thread data from TLS
ptd = _getptd();
// Wrap desired thread function in SEH frame to
// handle run-time errors and signal support.
__try {
// Call desired thread function, passing it the desired parameter.
// Pass thread's exit code value to _endthreadex.
_endthreadex (
((unsigned (WINAPI *)(void *))(((_ptiddata)ptd)->_initaddr))
(((_ptiddata)ptd)->_initarg)) ;
}
__except(_XcptFilter(GetExceptionCode(), GetExceptionInformation())){
// The C run-time's exception handler deals with run-time errors
// and signal support; we should never get it here.
_exit(GetExceptionCode());
}
}
关于_threadstartex函数,要注意一下几大重点:
1)新的线程首先执行RtlUserThreadStart(在NTDLL.dll文件中),然后再跳转到_threadstartex;
2)_threadstartex的参数是新线程的_tiddata内存块的地址;
3)TlsSetValue是一个操作系统函数,它将一个值与主调函数关联起来。这是所谓的线程局部存储(Thread Local Storage,TLS)。_threadstartex函数将_tiddata内存块与新建线程关联起来;
4)在无参数的辅助函数_callthreadstartex中,有一个SEH帧,它将预期要执行的线程函数包围起来。这个帧处理着与运行库有关的许多事情—比如运行时错误;
5)预期要执行的线程函数会被调用,并向其传递预期的参数。函数的地址和参数会被保存在TLS的_tiddata数据块中,并会在_callthreadstartex中从TLS中获取;
6)线程函数的返回值被认为是线程的退出代码;
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11