﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-byc-随笔分类-pthreads-w32</title><link>http://www.cppblog.com/byc/category/15470.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 15 Nov 2010 20:25:33 GMT</lastBuildDate><pubDate>Mon, 15 Nov 2010 20:25:33 GMT</pubDate><ttl>60</ttl><item><title>pthreads-w32</title><link>http://www.cppblog.com/byc/archive/2010/11/15/133666.html</link><dc:creator>八叶草</dc:creator><author>八叶草</author><pubDate>Mon, 15 Nov 2010 07:41:00 GMT</pubDate><guid>http://www.cppblog.com/byc/archive/2010/11/15/133666.html</guid><wfw:comment>http://www.cppblog.com/byc/comments/133666.html</wfw:comment><comments>http://www.cppblog.com/byc/archive/2010/11/15/133666.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/byc/comments/commentRss/133666.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/byc/services/trackbacks/133666.html</trackback:ping><description><![CDATA[<a href="http://shenan1984.blog.163.com/blog/static/2530851020098231001787/">http://shenan1984.blog.163.com/blog/static/2530851020098231001787/</a><br>&nbsp; official site: <a href="http://sourceware.org/pthreads-win32/"><font color=#675b8b>http://sourceware.org/pthreads-win32/</font></a>.&nbsp;<br>&nbsp; source co<wbr>de: <a href="ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz"><font color=#675b8b>ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz</font></a><br><br>1. 编译: <br>&nbsp;&nbsp;&nbsp; 虽然源码包里提供了vc6的项目文件, 但是打不开的, 只能用nmake. 默认的会告诉你一堆nmake参数的. <br>&nbsp;&nbsp;&nbsp; 我所要用的是编译成static的library, 所以输入"nmake clean VC-static", 编译很快的. 不过默认会链接到VC的crt, 我们需要修改它的makefile. 找到CFLAGS那一行, 把"/MD"改成"/MT". <br><br>2. 项目: <br>&nbsp;&nbsp;&nbsp; 诶.. 有好多地方要改的. <br>&nbsp;&nbsp;&nbsp; a) 当然是vs路径的include啊, lib啊.. 自己加. <br>&nbsp;&nbsp;&nbsp; b) 项目的crt设置成"/MT"和"/MTd". 额外的lib加: pthreadVC2(d).lib ws2_32.lib<br>&nbsp;&nbsp;&nbsp; c) preprocesser定义的地方, 加一个&#8220;PTW32_STATIC_LIB&#8221;宏, 不然link的时候会找不到symbol的. <br>&nbsp;&nbsp;&nbsp; d) 好了, 你可以coding了, 随便pthread_create()一把吧. <br><br>3. 编码: <br>&nbsp;&nbsp;&nbsp; 嗯嗯.. 如果真的直接pthread_create()的话可是会access violation的呀. win32下的线程很诡异的, 像winsock一样, 调用任何其它函数之前必须调用pthread_win32_process_attach_np(), 结束后必须调用pthread_win32_process_detach_np(). 代码大概就是这样的:<br><br>1. 下载pthreads win32源代码：<br>&nbsp;&nbsp;&nbsp; <a href="ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz">ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-8-0-release.tar.gz</a><br>2. 编译静态库：<br>make clean GC-static<br>在根目录下面生成libpthreadGC2.a<br>3. 将生成的libpthreadGC2.a拷贝到mingw库目录下，将pthread.h, sched.h, semaphore.h拷贝到INCLUDE目录下<br>4. 使用libpthread库，<br>在程序起始处对libpthread作初始化：<br>#if defined(PTW32_STATIC_LIB)<br>&nbsp;&nbsp;&nbsp; ptw32_processInitialize();<br>#endif<br>5. 编译时确保传入-DPTW32_STATIC_LIB，链接时加入-lpthreadGC2， OK！<br><br><br><a href="http://hi.baidu.com/lff0305/blog/item/2a55e7366ebba6360b55a942.html">http://hi.baidu.com/lff0305/blog/item/2a55e7366ebba6360b55a942.html</a><br>pthread2提供了不同的.lib以及相对应的.dll,
<p><span><font size=3>pthread[VG]{SE,CE,C}c.dll<br>pthread[VG]{SE,CE,C}c.lib</font></span></p>
<p>&#160;</p>
<p>含义为<br>[VG] 编译器种类<br>V&nbsp;&nbsp;&nbsp; - MS VC, or<br>G&nbsp;&nbsp;&nbsp; - GNU C</p>
<p>&#160;</p>
<p><span><font size=3>{SE,CE,C} 异常处理模式<br>SE&nbsp;&nbsp;&nbsp; - Structured EH, or<br>CE&nbsp;&nbsp;&nbsp; - C++ EH, or<br>C&nbsp;&nbsp;&nbsp; - no exceptions - uses setjmp/longjmp<br><br>c&nbsp;&nbsp;&nbsp; - DLL compatibility number indicating ABI and API<br>compatibility with applications built against<br>any snapshot with the same compatibility number.<br>See 'Version numbering' below.</font></span></p>
<p><span><font size=3>&nbsp;&nbsp; 比如上面用的pthreadvc2.dll, 含义为:</font></span><span><font size=3><br></font></span></p>
<p><span><font size=3>&nbsp;&nbsp; v = MSVC</font></span></p>
<p><span><font size=3>&nbsp;&nbsp; c = 没有使用异常机制, 而是使用setjump/longjmp</font></span></p>
<p><span><font size=3>&nbsp;&nbsp; 2 = 兼用性 - 和pthread2兼容, 不和旧版本pthread1兼容.</font></span></p>
<p>&#160;</p>
<p><span><font size=3>&nbsp;&nbsp; 详细请参照pthread的readme.<br></font></span></p>
<span><font size=3>
<p><br><a href="http://blog.csdn.net/psusong/archive/2010/01/14/5189659.aspx"><u><font color=#810081>http://blog.csdn.net/psusong/archive/2010/01/14/5189659.aspx</font></u></a><br><br>pthread 静态编译版本在Windows下使用时的注意事项 <br>作为通用的跨平台高性能线程库，在很多跨平台的项目中都可以看见pthread的身影。pthread本身的实现比较优雅，APIs使用起来也很方便。</p>
<p>但在Windows下使用静态编译的pthread时要特别注意一下，必须显式的调用如下四个函数，否则pthread用到的一些全局变量会没有被初始化，导致所有的pthread的APIs调用都crash.</p>
<p>BOOL pthread_win32_process_attach_np (void);</p>
<p>BOOL pthread_win32_process_detach_np (void);</p>
<p>BOOL pthread_win32_thread_attach_np (void);</p>
<p>BOOL pthread_win32_thread_detach_np (void);</p>
<p>pthread官方文档对此有如下的明确说明：</p>
<p>These functions contain the code normally run via dllMain</p>
<p>when the library is used as a dll but which need to be</p>
<p>called explicitly by an application when the library</p>
<p>is statically linked.</p>
<p>You will need to call pthread_win32_process_attach_np() before</p>
<p>you can call any pthread routines when statically linking.</p>
<p>You should call pthread_win32_process_detach_np() before</p>
<p>exiting your application to clean up.</p>
<p>pthread_win32_thread_attach_np() is currently a no-op, but</p>
<p>pthread_win32_thread_detach_np() is needed to clean up</p>
<p>the implicit pthread handle that is allocated to a Win32 thread if</p>
<p>it calls certain pthreads routines. Call this routine when the</p>
<p>Win32 thread exits.</p>
<p>These functions invariably return TRUE except for</p>
<p>pthread_win32_process_attach_np() which will return FALSE</p>
<p>if pthreads-win32 initialisation fails.</p>
<p>通过函数的名字我们不难猜测出如下调用顺序</p>
<p>在程序开始的时候要调用：</p>
<p>BOOL pthread_win32_process_attach_np (void);</p>
<p>BOOL pthread_win32_thread_attach_np (void);</p>
<p>在程序退出时要调用：</p>
<p>BOOL pthread_win32_thread_detach_np (void);</p>
<p>BOOL pthread_win32_process_detach_np (void);</p>
<p>比较通用的做法是在模块Load和UnLoad的时候做这个attach和detach操作，如下面所示：</p>
<p>/* Callback for our DLL so we can initialize pthread */</p>
<p>BOOL WINAPI DllMain( HANDLE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )</p>
<p>{</p>
<p>#ifdef PTW32_STATIC_LIB</p>
<p>&nbsp;&nbsp;&nbsp; switch( fdwReason )</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case DLL_PROCESS_ATTACH:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pthread_win32_process_attach_np();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case DLL_THREAD_ATTACH:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pthread_win32_thread_attach_np();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case DLL_THREAD_DETACH:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pthread_win32_thread_detach_np();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case DLL_PROCESS_DETACH:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pthread_win32_thread_detach_np();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pthread_win32_process_detach_np();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>#endif</p>
<p>&nbsp;&nbsp;&nbsp; return TRUE;</p>
<p>}</p>
<p>注意： PTW32_STATIC_LIB 宏为pthread静态编译的标志，这个可以通过pthread.h的配置或者CFLAGS传递进来。<br>下面是pthread的官方的dll.c的实现<br>BOOL WINAPI<br>DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)<br>{<br>&nbsp; BOOL result = PTW32_TRUE;<br>&nbsp; switch (fdwReason)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; case DLL_PROCESS_ATTACH:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = pthread_win32_process_attach_np ();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; case DLL_THREAD_ATTACH:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * A thread is being created<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = pthread_win32_thread_attach_np ();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; case DLL_THREAD_DETACH:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * A thread is exiting cleanly<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = pthread_win32_thread_detach_np ();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; case DLL_PROCESS_DETACH:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (void) pthread_win32_thread_detach_np ();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = pthread_win32_process_detach_np ();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; return (result);<br>} /* DllMain */<br>也就是说pthread官方代码在动态编译的版本中主动做了这个attach和detach操作。<br>而静态编译版本由于没有一个合适的地方来做这件事，就将attach和detach的的操作扔给用户来完成了。<br>上面的代码是针对调用方是Dll的情况做的初始化，如果调用方不是Dll呢？对此可以参照如下做法，虽然很暴力，但很简单，可以工作<br>1）定义如下函数<br>#ifdef PTW32_STATIC_LIB <br>static void detach_ptw32(void) <br>{ <br>&nbsp;&nbsp;&nbsp; pthread_win32_thread_detach_np(); <br>&nbsp;&nbsp;&nbsp; pthread_win32_process_detach_np(); <br>} <br>#endif <br>2）在你的主程序的入口处，一般而言是main()中做如下调用即可<br>#ifdef PTW32_STATIC_LIB <br>&nbsp;&nbsp;&nbsp; pthread_win32_process_attach_np(); <br>&nbsp;&nbsp;&nbsp; pthread_win32_thread_attach_np(); <br>&nbsp;&nbsp;&nbsp; atexit(detach_ptw32); <br>#endif <br>&nbsp;<br>也就是用atexit()将detach工作挂接到程序中去，使得程序在退出的时候可以对pthread进行detach.</p>
</font></span>
<img src ="http://www.cppblog.com/byc/aggbug/133666.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/byc/" target="_blank">八叶草</a> 2010-11-15 15:41 <a href="http://www.cppblog.com/byc/archive/2010/11/15/133666.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>