我可以将哪些同步原语与克隆(2)(C/C++)一起使用

What sync primitives can I use with clone(2) (C/C++)?

本文关键字:C++ 一起 同步原语 我可以      更新时间:2023-10-16

使用Linux的克隆(2)线程时,我可以使用哪些C++同步原语我特别不能使用pthreads,因为我正在构建一个共享库,用不同的定义替换许多pthreads的函数调用,但我需要某种互斥

EDIT:我可能说得太早了,我看了pthread文档,他们使用futex(2)来实现这些原语。我想我也会这么做吧?

您可以使用futexhttp://en.wikipedia.org/wiki/Futex

以下是基于futex的简单互斥和cond-varhttp://locklessinc.com/articles/mutex_cv_futex/

根据您对同步工具的要求,您还可以使用原子操作。例如,gcc的__sync_lock_test_and_set可以很容易地用于自旋锁。在许多情况下,这种避免系统调用的用户空间锁可能比基于内核的解决方案更高效。

编辑:如果您只有一些需要保护的说明,则会出现这种情况。那么,获取自旋锁的线程在保持锁的同时被中断的概率非常小如果发生这种情况,等待时间将是一些调度周期,而在现代系统中,这对实时系统来说应该是不可能的。对于平均等待时间来说,这应该可以忽略不计。

Ulrich Drepper的论文"futex很棘手"中描述了基于futex的Mutex的正确实现。osgx在评论中给出的链接已经过时。当前版本在这里:

http://people.redhat.com/drepper/futex.pdf

它不仅包括代码,还非常详细地解释了为什么它是正确的。论文中的代码:

class mutex
{
 public:
 mutex () : val (0) { }
 void lock () {
   int c;
   if ((c = cmpxchg (val, 0, 1)) != 0)
     do {
       if (c == 2 || cmpxchg (val, 1, 2) != 0)
         futex_wait (&val, 2);
     } while ((c = cmpxchg (val, 0, 2)) != 0);
 }
 void unlock () {
   if (atomic_dec (val) != 1) {
     val = 0;
     futex_wake (&val, 1);
   }
 }
 private:
   int val;
};

cmpxchg()和atomic_dec()可以分别通过__sync_val_compare_and_swap()和__sync_fetch_and_add()实现,它们不是标准C,但也由GCC和CLANG的AFAIK支持。

注意,futex()是特定于Linux的。FreeBSD有一个模拟AFAIK,但我不知道你是否可以本地访问它。如果您想针对Linux以外的其他平台,则不能使用futex()。但是,由于您使用的是特定于Linux的clone(),您可能不在乎。

关于你编写pthreads替代品的想法:

算了吧。

我自己走这条路是因为我想让clone()提供一些行为,而不是pthread_create()。过了一会儿我放弃了。glibc是建立在您使用pthreads的假设之上的。即使(或者特别是)不使用-lpthread链接,glibc也包含pthread特定的行为。让我放弃clone()的原因是错误。在多线程应用程序中,除非您想将每个libc调用与全局互斥体同步,否则必须提供线程本地errno。您可以通过实现__errno_location()来实现这一点。不幸的是,glibc在某些地方有自己的__errno_location硬编码,不会使用您的替换。

换句话说:如果你想使用自己的线程库,你就不能使用glibc,至少在不阅读你使用的每个函数的源代码并准备在必要时替换它的情况下是这样。如果你想使用uClibc,我会让你失望的。他们从glibc复制了部分实现,并且至少旧版本存在上述__errno_location问题。

我的解决方案是放弃对抗pthreads。我现在使用pthread_create()来创建线程(当然还有一个不错的C++包装器)。虽然我还没有尝试过,但unshare(2)系统调用应该允许我通过clone()更改线程的那些方面,而pthread_create()不支持这些方面。如果这不起作用,我将使用pthread_create()的glibc源代码,并将我的选项破解到它对clone()的调用中,保持其余部分相同,这样我就不会破坏兼容性。

至于同步原语:使用pthread_create()不会强制您使用pthread _mutex和company。因为我正在编写一个VM,其中每个对象都分配了一个互斥对象,所以我不想要pthread_mutex_t的空间开销。相反,我使用了上面论文中的Drepper Mutex类。您可以自由地混合和匹配pthread的基元和您自己的基元。只要可能,您应该使用pthread版本,因为它们经过了良好的测试。但是对于特殊情况(比如轻量级互斥),可以创建自己的基于futex的基元。