【问题标题】:errno in Multithread implementation多线程实现中的errno
【发布时间】:2013-07-12 09:49:46
【问题描述】:

要在多线程应用程序中使用 errno,此引用 http://www.cplusplus.com/reference/cerrno/errno/ 表明它应该在每个线程中本地实现。这是什么意思?

【问题讨论】:

    标签: c++ c errno


    【解决方案1】:

    errno 应该是 thread-local。在每个thread这个变量的值可以不同。

    应该在每个线程中本地实现

    errno 实现为thread_local 变量不是您的职责。它适用于编译器开发人员。

    来自cppreference.com

    errno 是用于错误指示的预处理器宏。 它扩展为 int 类型的线程局部可修改左值。(C++11 起)

    仅在 C++11 编译器中,此代码不应断言

    #include <iostream>
    #include <cerrno>
    #include <thread>
    #include <cassert>
    
    int g_errno = 0;
    
    void thread_function()
    {
       errno = E2BIG;
       g_errno = errno;
    }
    
    int main()
    {
       errno = EINVAL;
       std::thread thread(thread_function);
       thread.join();
       assert(errno != g_errno && "not multithreaded");
    }
    

    【讨论】:

    • 我的问题是如何做到这一点?通常的程序是包含头文件#include 并直接使用errno。如何使其本地化?
    • 上述参考说:“支持多线程的库应在每个线程的基础上实现 errno:每个线程都有自己的本地 errno”。在实现层面它看起来如何?
    • @WildThing 来自 C++ 标准:应为每个线程提供单独的 errno 值。 “库”实际上意味着实现。
    • 所以我在我的类中包含 errno.h 并使用 errno 来实现多线程而无需任何其他修改?
    • @WildThing 完全正确。如果您使用实现此功能的 C++11 编译器。
    【解决方案2】:

    从历史上看,errnoint 类型的common 变量——即每个模块都有自己的定义,链接器负责合并它们。所以程序在全球范围内简单地声明int errno;,并有一个工作定义。

    这在多线程环境中会失效,因为只有一个变量。因此,errno.h 现在需要定义一个左值 int,程序不应该定义自己的errno

    例如,GNU C 库定义了类似于

    #define errno (*(__errno_location()))
    

    其中__errno_location() 是一个内联函数,用于计算线程本地errno 的地址。

    所有这些都与应用程序无关,除了定义自己的errno 是错误的。

    【讨论】:

    • 它真的是一个公共变量吗?我以为是libc中定义的外部变量。
    • @Maxim,是的——extern int errno; 也有效,因为它也可以用来指代一个通用定义。但是,使用 int errno = 0; 初始化无法链接。
    【解决方案3】:

    这意味着每个线程都应该有自己的errno变量实例

    实现可以通过使用类似的东西轻松实现:

    int __thread errno;
    

    __thread 是一个 gcc 扩展,可确保变量是线程本地的(因此一个线程不能覆盖该变量的另一个线程实例)

    作为 errno 的用户,您无需担心这一点。您甚至不必担心 errno 可能已被另一个线程抢先更改。

    【讨论】:

    • 你能详细描述一下这个过程吗?
    猜你喜欢
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    相关资源
    最近更新 更多