mingw-w64线程:posix vs win32

180
我正在Windows上安装mingw-w64,有两个选项:win32 threads和posix threads。我知道win32 threads和pthreads之间的区别,但我不明白这两个选项之间的区别。我怀疑如果我选择posix threads,则无法调用像CreateThread这样的WinAPI函数。
似乎此选项指定某个程序或库将使用哪个线程API,但是由谁来指定?由GCC、libstdc++还是其他什么?
我找到了这个: Whats the difference between thread_posixs and thread_win32 in gcc port of windows? 简而言之,对于mingw的这个版本,threads-posix发布将使用posix API并允许使用std::thread,threads-win32将使用win32 API,并禁用标准中的std::thread部分。
如果我选择win32 threads,则std :: thread将不可用,但win32 threads仍将被使用。但是被什么使用?

使用 this gcc 创建的应用程序所使用。 - devnull
@devnull,这不是由我使用的API决定的吗?如果我选择MinGW的pthreads版本,那么有什么阻止我使用WinAPI来进行线程操作呢? - Simon
gcc会阻止你,或者说:变得不稳定。 - jiggunjer
3
我看到了这篇有关MinGW-w64在Windows上进行配置的Visual Studio Code文章(https://code.visualstudio.com/docs/cpp/config-mingw),他们似乎选择了posix版本(也是x86_64和seh)。 - Jeromy Adofo
4个回答

177
GCC附带一个编译器运行时库(libgcc),用于提供低级OS抽象以支持其支持的语言中与多线程相关的功能。最相关的例子是libstdc ++的C++11 <thread><mutex><future>,如果GCC使用其内部Win32线程模型构建,则这些功能没有完整实现。MinGW-w64提供了winpthreads(基于Win32多线程API的pthread实现),GCC可以将其链接以启用所有花哨的功能。
我必须强调这个选项不会禁止您编写任何想要的代码(它绝对不会影响您在代码中可以调用的API)。它只反映了GCC运行时库(libgcc/libstdc++/...)用于其功能的情况。@James引用的警告与GCC的内部线程模型无关,而与Microsoft的CRT实现有关。
总结一下:
  • posix: 启用C++11/C11多线程特性。使libgcc依赖于libwinpthreads,因此即使您不直接调用pthread API,也会分发winpthreads DLL。在应用程序中分发一个DLL没有问题。
  • win32: 没有C++11多线程特性。
两者都不会影响调用Win32 API或pthread API的任何用户代码。您始终可以同时使用两者。

16
您可以始终静态链接gcc运行时和winpthreads,从而消除了必须包含DLL的必要性。 - Alexander Shishenko
10
在Linux上,我花了一段时间才找到相应的选项,所以如果有人需要帮助的话:包 g++-mingw-w64-x86-64 提供了两个文件 x86_64-w64-mingw32-g++-win32x86_64-w64-mingw32-g++-posix,而 x86_64-w64-mingw32-g++ 是它们中的一个别名;请参见 update-alternatives --display x86_64-w64-mingw32-g++ - stewbasic
3
嗯,你说:“当GCC使用其内部Win32线程模型构建时,某些功能没有完整的实现... MinGW-w64提供了winpthreads(在Win32多线程API之上的pthread实现),GCC可以将其链接以启用所有花哨的功能。”所以如果我选择win32模型,GCC仍然可以启用所有功能,因为它利用了winpthreads?但是在下面的项目符号中,你写道“win32:没有C++11多线程功能”。我不明白。 “GCC可以将其链接到...”是否意味着如果我选择win32,那么它就可以选择...? - Johannes Schaub - litb
1
没有人写过一本书。我只是接近那些设置这个并为其他人提供了一个链接到libstdc++的winpthreads的第一个(第一个之一?)构建的人。 - rubenvb
1
GCC的libstdc++在posix线程之上实现了std::thread。它将这个选择与其在libstdc++中提供的内容联系起来。选择在GCC中使用posix线程并不妨碍您在代码中使用win32 API线程。选择在GCC中使用win32线程也不会阻止您通过单独的winpthreads库使用pthread。唯一取决于GCC的posix/win32线程的是生成的libstdc++可用的功能。 - rubenvb
显示剩余8条评论

21

GCC运行库的某些部分(特别是异常处理)依赖于正在使用的线程模型。因此,如果您使用了与POSIX线程一起构建的运行时版本,但决定在您自己的代码中使用Win32 API创建线程,则可能会在某个时候遇到问题。

即使你正在使用Win32线程版本的运行时,你也可能不应该直接调用Win32 API。引用来自MinGW FAQ

由于MinGW使用随Windows提供的标准Microsoft C运行时库,因此您应该小心并使用正确的函数生成新线程。特别是,CreateThread函数将不会为C运行时库正确设置堆栈。相反,您应该使用_beginthreadex,它(几乎)完全兼容CreateThread


7
在这种情况下,那么像boost或Qt这样的第三方线程库怎么办?有没有办法在mingw64上使用这些库而不必了解这些库的底层线程库?如果我任意决定在posix变体的mingw中使用boost::threads会发生什么? - tantuni
1
@user460153 一些信息 http://qt-project.org/wiki/MinGW-64-bit#03a4097f5708a02b5f19f72476b49adc - rtxndr
15
这个回答是错误的。GCC运行库对Win32 API完全没有任何影响。 - rubenvb
1
@rubenvb 这个答案在客户端程序规则方面是正确的,尽管有些误导关于原因。ISO C++中很少有公共的互操作性保证,几乎没有这样的保证由MinGW运行时来确保实现定义的事情将来绝对不会改变(实际上一些在libstdc++文档中,超出了MinGW的范围)。GCC也不公开线程模型实现的详细信息作为公共API,因此不能假定它们与Win32 API之间存在映射。 - FrankHB

16
注意,现在可以在 win32 线程模式下使用一些 C++11 std::thread。这些仅限头文件的适配器可以直接使用: https://github.com/meganz/mingw-std-threads 从修订历史记录来看,似乎最近有一些尝试将其作为 mingw64 运行时的一部分。

1

@rubenvb的回答是完全正确的,如果你想使用std::threadstd::mutex等,请使用mingw posix编译器。对于所有使用CMake的人,这里有一个例子:

set(CMAKE_CXX_STANDARD 17) # or 20 if you want..
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)

set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)

set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc-posix)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++-posix)
set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres)

set(CMAKE_FIND_ROOT_PATH
  /usr/${TOOLCHAIN_PREFIX}
)

适用于将Linux应用程序交叉编译到Windows。

提示:对于使用GTK3并希望将其GTK应用程序交叉编译到Windows的人。您可能想要下载Mingw Windows GTK捆绑包,该捆绑包从msys2.org下载和打包,因此您不需要:https://gitlab.melroy.org/melroy/gtk-3-bundle-for-windows


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接