Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何创建一个仅在链接pthread时才使用互斥体的库?_C_Linux_Gcc_Pthreads_Freebsd - Fatal编程技术网

C 如何创建一个仅在链接pthread时才使用互斥体的库?

C 如何创建一个仅在链接pthread时才使用互斥体的库?,c,linux,gcc,pthreads,freebsd,C,Linux,Gcc,Pthreads,Freebsd,我正在Linux上创建一个C库,它有几个函数,这些函数一起操作一些全局数据。为了使这些函数是线程安全的,它们必须在代码中的适当位置使用互斥体 在Linux中,为了在应用程序中使用pthreads,需要在适当的库中链接-lpthread。在我的库编译后的情况下,如果它的用户决定在他们的应用程序中使用pthreads,或者如果他们不使用pthreads,我希望它能够工作 如果开发人员在其应用程序中不使用线程,他们将不会链接到pthreads。因此,我希望我的编译库不需要它,而且,在单线程应用程序中使

我正在Linux上创建一个C库,它有几个函数,这些函数一起操作一些全局数据。为了使这些函数是线程安全的,它们必须在代码中的适当位置使用互斥体

在Linux中,为了在应用程序中使用pthreads,需要在适当的库中链接-lpthread。在我的库编译后的情况下,如果它的用户决定在他们的应用程序中使用pthreads,或者如果他们不使用pthreads,我希望它能够工作


如果开发人员在其应用程序中不使用线程,他们将不会链接到pthreads。因此,我希望我的编译库不需要它,而且,在单线程应用程序中使用互斥体会使用不必要的开销(更不用说这是愚蠢的)

是否有某种方式可以编写代码(如果需要,可以使用GCC扩展),使某个代码块仅在链接了某些符号的情况下运行?我知道我可以使用dlopen()和friends,但这本身就需要一些我试图避免的东西。我想我所寻找的必须存在,因为几个标准函数都在同一条船上,并且需要互斥锁是线程安全的(它们确实是),但即使没有与pthread链接也可以工作

在这一点上,我注意到第66和67行使用了一个不可移植的检查-isthreaded,以确定是否使用线程,以及是否使用互斥体。我怀疑这样的事情在任何方面都是标准化的。但更重要的是,如果无法识别符号,这些代码将无法编译和链接,而在Linux中,如果不链接pthread,互斥符号甚至不会出现


总而言之:在Linux上,如何创建一个库,它知道何时也使用线程,如果是,则在适当的情况下使用互斥体,并且不需要针对pthread进行链接,除非应用程序开发人员特别希望在某处使用线程?

经过一些测试,看来Linux已经自动完成了我想要的!如果您使用线程,则只需要针对pthread进行链接,而不是只需要pthread互斥体支持

在本测试案例中:

#include <stdio.h>
#include <errno.h>
#include <pthread.h>

int main()
{
  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

  if (!(errno = pthread_mutex_lock(&mutex))) { puts("Mutex locked!"); }
  else { perror("Could not lock mutex"); }

  if (!(errno = pthread_mutex_lock(&mutex))) { puts("Mutex locked!"); }
  else { perror("Could not lock mutex"); }

  return 0;
}
#包括
#包括
#包括
int main()
{
pthread\u mutex\u t mutex=pthread\u mutex\u初始值设定项;
如果(!(errno=pthread_mutex_lock(&mutex)){put(“mutex locked!”);}
else{perror(“无法锁定互斥锁”);}
如果(!(errno=pthread_mutex_lock(&mutex)){put(“mutex locked!”);}
else{perror(“无法锁定互斥锁”);}
返回0;
}
在没有链接pthreads的情况下编译时,我看到“Mutex locked!”两次。这表明pthread_mutex_lock()本质上是一个非操作。但是在pthread链接的情况下,运行此应用程序将在第一次打印“mutex lock!”后暂停


因此,我可以在适当的情况下在我的库中使用互斥体,并且不需要使用pthread,在不需要的情况下不需要(显式?)开销。

通常的解决方案是:

  • 使用
    #define
    开关在构建时控制是否调用pthreads函数,并让构建过程创建两个版本的库:一个支持pthread,另一个不支持pthread,名称不同。依靠您的库的用户来链接正确的库

  • 不要直接调用pthreads函数,而是调用用户提供的
    lock
    unlock
    回调(如果需要,还可以调用线程本地存储)。库用户负责分配和调用适当的锁定机制,这也允许他们使用非pthreads线程库

  • 什么都不做,只记录用户代码,以确保库函数不会同时从多个线程输入

  • glibc再次做了一些不同的事情——它使用带有惰性绑定符号的技巧,仅当pthreads函数链接到二进制文件时才调用它们。但这不是可移植的,因为它依赖于pthreads的glibc实现的特定细节。见:


    “如果开发人员在其应用程序中不使用线程,他们将不会链接到pthreads。”-但您的库会。或者,如果它是静态库,它将包含大量必须由调用程序解析的外部pthread引用,即使它们不使用pthread。如果没有一对pthread/no pthread共享对象模块,没有调用方的初始化配置,没有运行时加载的正确的dyna,没有非pthread配置中所有锁定操作的stubbed,我想你不会得到你想要的,并让应用程序为您提供一组锁。RSA BSAFE CryptoC ME就是这样做的,例如,它要求应用程序提供一个回调函数,该函数尽职尽责地使用它自己的“锁表”,大小为库头指定的预定义的
    #define
    大小,需要多少个“锁”。每个锁操作都通过索引传递给回调,并使用一个var说明操作请求是什么(lock,UNLOCK)。然后,应用程序可以在知道它是单线程的情况下,简单地提供一个总是返回true的回调,而不做任何其他事情。FreeBSD和NetBSD在这里与Linux具有相同的语义,这很好,需要OpenBSD-lpthread。另一方面,当与-lpthread链接时,FreeBSD和OpenBSD在第二个锁处都没有挂起,而是返回了避免的死锁。所有BSD似乎也定义了uu isthreaded in,这样就可以检查是否有线程在实际使用中。关于u isthreaded,事实证明NetBSD和Debian kFreeBSD都缺少它。DragonFlyBSD与FreeBSD不相上下。对于OpenBSD,要实现我想要的功能,需要利用:int pthread_mutex_lock(pthread_mutex_t*mutex)uu属性__((弱));
    #ifdef __PIC__
    # define __libc_maybe_call(FUNC, ARGS, ELSE) \
      (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \
                        _fn != NULL ? (*_fn) ARGS : ELSE; }))
    #else
    # define __libc_maybe_call(FUNC, ARGS, ELSE) \
      (FUNC != NULL ? FUNC ARGS : ELSE)
    #endif