mingw-w64 线程:posix vs win32

Posted

技术标签:

【中文标题】mingw-w64 线程:posix vs win32【英文标题】:mingw-w64 threads: posix vs win32 【发布时间】:2013-06-19 00:20:39 【问题描述】:

我正在 Windows 上安装 mingw-w64,有两个选项:win32 线程和 posix 线程。我知道win32线程和pthreads有什么区别,但我不明白这两个选项有什么区别。我怀疑如果我选择 posix 线程,它会阻止我调用像 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 线程,则 std::thread 将不可用,但仍将使用 win32 线程。但被什么使用?

【问题讨论】:

由使用 this gcc 创建的应用程序使用。 @devnull,这不是由我将使用的 API 决定的吗?如果我将选择 pthreads 版本的 MinGW,那么什么会阻止我将 WinAPI 用于线程? gcc 会阻止你,或者更确切地说:变得不稳定 我看到了这篇关于为 Windows 配置 MinGW-w64 的 Visual Studio Code 文章 (code.visualstudio.com/docs/cpp/config-mingw),他们似乎已经选择了 posix 版本(还有 x86_64 和 seh)。 【参考方案1】:

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

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

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

【讨论】:

在这种情况下,像 boost 或 Qt 这样的第 3 方线程库呢?有什么方法可以将这些库与 mingw64 一起使用,而无需找出这些库的底层线程库?如果我任意决定将 boost::threads 与 mingw 的 posix 变体一起使用会发生什么? @user460153 一些信息qt-project.org/wiki/… 这个答案是错误的。 GCC 运行时对 Win32 API 完全没有影响。【参考方案2】:

GCC 带有一个编译器运行时库 (libgcc),它用于(除其他外)为它支持的语言中的多线程相关功能提供低级操作系统抽象。最相关的例子是 libstdc++ 的 C++11 <thread><mutex><future>,当 GCC 使用其内部 Win32 线程模型构建时,它们没有完整的实现。 MinGW-w64 提供了一个 winpthreads(在 Win32 多线程 API 之上的一个 pthreads 实现),然后 GCC 可以链接到它以启用所有花哨的功能。

我必须强调这个选项不会禁止你编写任何你想要的代码(它绝对NO影响你可以在你的代码中调用什么 API)。它仅反映 GCC 的运行时库 (libgcc/libstdc++/...) 用于其功能的内容。 @James 引用的警告与 GCC 的内部线程模型无关,而是与 Microsoft 的 CRT 实现有关。

总结一下:

posix:启用 C++11/C11 多线程特性。使 libgcc 依赖于 libwinpthreads,因此即使您不直接调用 pthreads API,您也将分发 winpthreads DLL。在您的应用程序中再分配一个 DLL 并没有错。 win32:没有 C++11 多线程特性。

对调用 Win32 API 或 pthreads API 的任何用户代码均无影响。您可以随时使用两者。

【讨论】:

您始终可以静态链接 gcc 运行时和 winpthread,无需包含 DLL。 我花了一段时间才在 Linux 上找到了相应的选项,所以以防万一:包g++-mingw-w64-x86-64 提供了两个文件x86_64-w64-mingw32-g++-win32x86_64-w64-mingw32-g++-posixx86_64-w64-mingw32-g++ 是别名为其中之一;见update-alternatives --display x86_64-w64-mingw32-g++ 嗯,你说“......当 GCC 使用其内部 Win32 线程模型构建时,它没有完整的实现...... MinGW-w64 提供了一个 winpthreads(一个 pthreads 实现在Win32 多线程 API),然后 GCC 可以链接到该 API 以启用所有花哨的功能。”所以如果我选择win32模型,GCC仍然可以启用所有功能,因为它使用了winpthreads?但在下面的项目符号中,您写的是“win32:没有 C++11 多线程特性”。我不明白。 “然后哪个 GCC 可以链接到...”是否意味着如果我选择 win32,那么它可以选择...? @JohannesSchaub-litb 好吧,不。 GCC 的配置魔法将内部线程模型选择与 libstdc++ 启用的特性相结合,因为后者构建在 GCC 的内部“gthread”包装器之上(这只是一个类似于 posix 的细线程抽象。缺少 C++11 特性的基本部分当您使用--threads=win32时,在该层中。所以只要缺少的位没有在GCC中实现,您必须使用--threads=win32配置GCC。 我可以将qt的mingw预编译库(使用-win32)与其他使用-posix的库一起使用,并在同一个程序中使用这两个库吗?【参考方案3】:

请注意,现在可以在 win32 线程模式下使用某些 C++11 std::thread。这些仅包含标头的适配器对我来说是开箱即用的: https://github.com/meganz/mingw-std-threads

从修订历史来看,最近有人尝试将其作为 mingw64 运行时的一部分。

【讨论】:

【参考方案4】:

@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

【讨论】:

以上是关于mingw-w64 线程:posix vs win32的主要内容,如果未能解决你的问题,请参考以下文章

使用 mingw-w64 编译 mex 的链接器错误

MinGW vs MinGW-W64及其它

c++编译thread程序时加了<thread>但他就是给我报错说没加,我装了个mingw-w64也不行,咋回事?

[科普]MinGW vs MinGW-W64及其它(比较有意思,来自mingw吧)

如何使用预处理器检测 GCC 线程模型?

mingw w64 安装问题