首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > windows >

windows平台的多线程同步互斥:从内核源码分析-小话多线程(三)

2012-08-27 
windows平台的多线程同步互斥:从内核源码分析----小话多线程(3)作者:陈曦 日期:2012-8-16 13:05:34环境:[w

windows平台的多线程同步互斥:从内核源码分析----小话多线程(3)
作者:陈曦

日期:2012-8-16 13:05:34

环境:[win7 32位操作系统  Intel i3 支持64位指令   VS2010;   wrk-v1.2 ;   Source Insight]  

转载请注明出处


Q1: 举个windows平台简单的线程例子吧。

A: 如下,保存为thread_test.c:

可以看到,获得了此线程的ID和所属进程的ID; 我们同时可以从任务管理器中查看:

windows平台的多线程同步互斥:从内核源码分析-小话多线程(三)

这里也可以看到,PID确实是输出的那样,线程数为1,这表明只有一个主线程。如果希望查看更多的信息,可以使用微软提供的procexp.exe(sysinternals提供)查看:

windows平台的多线程同步互斥:从内核源码分析-小话多线程(三)

可以看到上面thread_text.exe进程所属的位置。双击进入:

windows平台的多线程同步互斥:从内核源码分析-小话多线程(三)

这里可以看到,此线程的ID,确实是上面输出的7416; 同时也可以看到,此线程是从_mainCRTStartup运行的。点击stack按钮查看具体堆栈信息:

windows平台的多线程同步互斥:从内核源码分析-小话多线程(三)

上面的图示具体描述了此线程运行的堆栈信息,同时也可以看到线程运行在不同模块的位置(注意: ntkr128g.exe是本机因为要识别4G内存新安装的内核,正常情况下是ntoskrnl.exe或者ntkrnlpa.exe. ). 这里也可以看到线程运行于内核状态调用的关系。



Q2: CreateThread和_beginthread到底有什么区别?为什么人们老说使用CreateThread可能导致内存泄露?

A: 从目的的角度来说,它们都是为了创建一个线程;但是具体到细节,它们又有不同:前者是系统API,这意味着它没有和通常程序会使用的C库等库绑定,后者是微软提供的c运行时函数。所以,_beginthread可能会做一些维持c库正常运行的事情,而CreateThread函数就很单纯。查看它们的源代码会很容易找到它们的区别,这里就不贴代码了。

如果已经知道它们所属的层次不同,就很容易理解为什么CreateThread创建线程可能会导致内存泄露了。

不过在win7或者2003 server等平台上,即使使用CreateThread创建子线程, 子线程中调用c库函数strtok, 依然不会发生泄露,原因在于线程退出释放Fiber Local Storage从而正确地释放了线程局部存储的数据。

如下代码:

可以看到,子线程退出线程过程中执行了_freefls函数,它的内部将释放TLS结构ptd.

当然,依然要注意:此程序链接C库的方式是静态链接,即采用/MT或者/MTd方式,而不是采用动态链接DLL的方式/MD或者/MDd的方式。因为采用动态链接C库的方式DLL初始化和退出时会自动释放TLS数据,而无法验证ExitThread是否释放TLS.

另外,正如上面之前提到的,我在win7以及windows server 2003的虚拟机上面运行程序,都符合上面的分析,即CreateThread创建线程后线程内部调用使用TLS结构的函数,比如strtok后,并不会造成内存泄露;但是,我在XP上运行此程序,就发现了内存泄露。具体就不贴图了,大家可以自行测试(最好使用while循环不断创建线程这样很明显观察到内存泄露的过程,在win7或者windows server 2003上,内存会上下浮动,但是随着线程结束释放了对应的结构,进程占用的内存始终保持在一个小波动的范围,而在xp上明显能看到内存使用迅速增加)。

不过不管一个进程泄露了多少内存,最终进程结束的时候都会释放这些内存,所以当结束后,这些内存被回收了,不用害怕你的机器运行了几次内存没了。

另外,我查了一下ntdll.dll模块中_RtlProcessFlsData函数的出处,发现它是从vista系统开始引入的,所以我猜测vista系统和上面的win7, server 2003运行情况类似,这个没有测试,如果谁正好有这个系统或虚拟机,方便测试,可以帮忙测试一下。 


Q3: CreateEvent创建的事件对象和CreateMutex创建的互斥体到底有什么区别?

A: 其实event直观的感觉更倾向于同步,而mutex更倾向于互斥;但是,同步互斥本来就不是矛盾体,同步有时就意味着互斥,互斥也就意味着需要同步,很多时候它们是结合在一起使用的。对于mutex不再举例,下面对于event举个例子,保存为test_event.c:



Q4: 形如上面的例子CreateEvent创建的event在内核中到底是什么?

A: 为了更清楚地弄清楚它到底是什么,我们先查看内核源代码(wrkv1.2, nt内核源代码,windows xp, windows server 2003内核源代码)。

VOIDFASTCALLKiUnwaitThread (    IN PRKTHREAD Thread,    IN LONG_PTR WaitStatus,    IN KPRIORITY Increment    )/*++Routine Description:    This function unwaits a thread, sets the thread's wait completion status,    calculates the thread's new priority, and either readies the thread for    execution or adds the thread to a list of threads to be readied later.Arguments:    Thread - Supplies a pointer to a dispatcher object of type thread.    WaitStatus - Supplies the wait completion status.    Increment - Supplies the priority increment that is to be applied to        the thread's priority.Return Value:    None.--*/{    //    // Unlink thread from the appropriate wait queues and set the wait    // completion status.    //    KiUnlinkThread(Thread, WaitStatus);    //    // Set unwait priority adjustment parameters.    //    ASSERT(Increment >= 0);    Thread->AdjustIncrement = (SCHAR)Increment;    Thread->AdjustReason = (UCHAR)AdjustUnwait;    //    // Ready the thread for execution.    //    KiReadyThread(Thread);    return;}

我想我不用解释KiReadyThread的意义了。当然,对于其它同步互斥对象,比如mutex, 实现互斥的过程也是类似的,这里不一一列举了。


Q5: windows上可以使用pthread函数库吗?

A: 微软官方貌似没有发布pthread库,但是有开源代码,详情请进:http://sources.redhat.com/pthreads-win32/



作者:陈曦

日期:2012-8-16 13:05:34 

环境:[win7 32位操作系统  Intel i3 支持64位指令   VS2010;   wrk-v1.2 ;  Source Insight]  

转载请注明出处


热点排行