C 禁用线程支持

C 禁用线程支持,c,linux,pthreads,C,Linux,Pthreads,我正在实现一个非常轻量级的pthread替换库。我想完全禁用线程有几个原因 这是浪费记忆。如果我正在创建一千个线程,而这些线程与用_线程声明变量的上下文无关,那么它们仍然会分配程序,仍然会分配1000*数据字节的大小,并且永远不会使用它。它与大规模并发模型的内存不兼容。如果我们需要只有8K堆栈的超轻光纤,那么仅4K的TLS块将是每个线程所用内存的50%的开销。在某些情况下,TLS开销将是巨大的 TLS是一个复杂的标准,我根本没有时间/资源来支持它。太贵了。我个人认为这个标准设计得很糟糕。它应该定

我正在实现一个非常轻量级的pthread替换库。我想完全禁用线程有几个原因

  • 这是浪费记忆。如果我正在创建一千个线程,而这些线程与用_线程声明变量的上下文无关,那么它们仍然会分配程序,仍然会分配1000*数据字节的大小,并且永远不会使用它。它与大规模并发模型的内存不兼容。如果我们需要只有8K堆栈的超轻光纤,那么仅4K的TLS块将是每个线程所用内存的50%的开销。在某些情况下,TLS开销将是巨大的
  • TLS是一个复杂的标准,我根本没有时间/资源来支持它。太贵了。我个人认为这个标准设计得很糟糕。它应该定义必须由链接器提供的标准函数,以便线程库可以控制TLS分配发生的位置,并插入所需的相关偏移量和地址。另外,标准ELF实现已经感染了pthread,期望pthread大小的结构计算偏移量,这使得它很难适应其他东西
  • 这只是一个坏模式。它鼓励使用全局函数并创建具有静态函数/副作用的函数。如果我们正在创建易于分析的正确程序,那么这不是我们想要进入的领域
  • 如果我们真的需要“线程上下文”来实现一些幕后跟踪线程状态的魔术(比如分配或取消跟踪),为什么不首先公开TLS用来理解该上下文的魔术呢?就我个人而言,我将直接使用
    %fs
    寄存器。这在库中是不可能的,原因很明显,但为什么它们一开始就应该有线程意识呢?为什么不正确地设计它们,让它们在参数列表中首先获得所需的上下文相关数据呢

  • 我的问题很简单:如果您不小心使用了线程支持,那么禁用线程支持并使其发出错误的最简单方法是什么?如果我加载了一个需要TLS的动态库,我怎么会出错呢?

    我认为最简单的方法是无条件地将这样的东西添加到您的CFLAG中(如果您希望它是系统全局的,可能来自clang的gcc规范文件的等价物):

    在C程序中,右边可以是任何语法上无效的东西(违反约束)

    至于防止使用TLS加载库,您必须修补链接器和/或动态链接器以拒绝它们。如果您只是在谈论
    dlopen
    ,那么您的程序可以首先读取文件并解析TLS重新定位的ELF头,然后拒绝库(如果有库,则不将其传递给
    dlopen
    )。这甚至可以通过
    LD\u预加载
    包装器实现

    我同意你的观点,特别是在它当前的实现中,TLS是一种通常应该避免使用的东西,但是我想问一下,你是否衡量了成本?我认为,在一个专门为使用它而设计的系统上,完全消除它将是相当困难的,而且在减少浮肿方面,它的成功率要低得多。您使用的是哪种libc?如果是glibc,我敢肯定glibc现在有很多TLS在内部使用。。。当然,如果您正在编写自己的线程实现,那么将需要与标准库的其余部分进行大量交互,所以您可能已经在修补它了



    顺便说一句(无耻插头如下),我们有一个目前没有TLS的。我认为与另一个libc集成并不容易(我相信,如果你正在编写自己的libc,你会发现与glibc集成很困难,特别是glibc的动态链接器,它希望TLS得到支持),但如果你能按原样使用整个库,它可能会满足你对特定项目的需求,或者你可以借用有用的代码(许可证是MIT)。

    什么是TLA?您的意思是TLS=线程本地存储,即GCC的限定符?你可以
    #定义#线程@error#u线程#####(行)()(行)()
    (基本行)谢谢,我是指TLS。修正了打字错误。这是一个解决方案。编译器级而非预处理器级的东西会更好,而且#define不会阻止使用#线程的动态库被意外使用。也许你可以使用一些链接器脚本技巧来避免这种情况。你说它将分配1000*数据大小是什么意思?数据在需要时才被保留。我最近修复了一个链接器错误,并且正在挖掘代码。我同意这是缓慢的访问,虽然。。。大量的开销。@jszakmeister:静态TLS实际上是立即在线程堆栈上分配的(在pthread结构之后),并且只要程序触及同一页中的任何其他地址(这很可能),就会占用物理进程内存。动态TLS块在需要时进行malloc'd,但会遇到相同的问题。如果一个线程只使用该块中1%的数据,它仍将物理上保留同一页中的所有其他数据。仅供参考:
    musl libc
    显然不能使用
    gcc-4.7
    构建,使用
    CFLAGS='-O3-g-flto'
    @Basile:感谢您的报告。不幸的是,链接libc.so的似乎是一个ICE(内部编译器错误),因此在不调试工具链本身的情况下很难知道原因……我得到的不是ICE,而是一个多定义的
    \u environ
    ;请随时给我发电子邮件询问更多细节。@R.我刚刚给你发了一封电子邮件,上面有我的系统上make的详细输出和更多细节。是的,这些错误看起来很荒谬;源代码中引用多个定义的位置与
    \uuuu environ
    无关。我认为这是一个GCC错误。
    -D__thread='^-^'