C Pthreads和不透明类型
我正在阅读pthreads库的头文件,在bits/pthreadtypes.h中找到了互斥体(和其他类型)的这个特定定义:C Pthreads和不透明类型,c,struct,pthreads,unions,C,Struct,Pthreads,Unions,我正在阅读pthreads库的头文件,在bits/pthreadtypes.h中找到了互斥体(和其他类型)的这个特定定义: typedef union { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; /* KIND must stay at this position in the structure to maintain binary
typedef union
{
struct __pthread_mutex_s
{
int __lock;
unsigned int __count;
int __owner;
/* KIND must stay at this position in the structure to maintain
binary compatibility. */
int __kind;
unsigned int __nusers;
__extension__ union
{
int __spins;
__pthread_slist_t __list;
};
} __data;
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
它并不完全像这样,但为了清晰起见,我简化了它。在头文件和实现文件中创建一个具有两个不同定义的结构,作为实现—实际结构定义和头文件—只是实际结构大小的字符缓冲区—用作隐藏实现的技术(不透明类型)但在调用malloc或在堆栈中分配对象时,仍然要分配正确的内存量
这个特定的实现使用一个并集,并且仍然公开结构和字符缓冲区的定义,但是在隐藏类型方面似乎没有提供任何好处,因为结构仍然公开,二进制兼容性仍然依赖于结构不变
IEEE和POSIX等标准委员会通过迭代开发和发展标准,以提供更多功能或纠正标准先前版本的问题。这个过程是由有问题域软件需求的人的需求以及支持这些人的软件产品的供应商驱动的。通常,标准的实施在不同供应商之间会有所不同。与任何其他软件一样,不同的人根据目标环境以及他们自己的技能和知识提供不同的实现。然而,随着标准的成熟,出现了一种达尔文式的选择,其中就最佳实践达成了一致,各种实现开始趋同 pthreads POSIX库的第一个版本是在20世纪90年代,目标是UNIX风格的操作系统环境,例如see和see。该库的思想和概念源于早些时候所做的工作,其目的是提供协同例程或线程类型的功能,该功能在比操作系统进程级别更精细的级别上工作,以减少创建、管理和销毁进程所涉及的开销。有两种主要的线程处理方法,一种是内核支持很少的用户级线程,另一种是内核级线程,这取决于提供线程管理的操作系统,具有一些不同的功能,例如先发制人的线程切换或不可用 此外,调试器等工具制造商还需要为在多线程环境中工作提供支持,并能够查看线程状态和识别特定线程 在库的API中使用不透明类型有几个原因。主要原因是允许库的开发人员灵活地修改类型,而不会给库的用户带来问题。在C中有几种创建不透明类型的方法 一种方法是要求API用户使用指向由API库管理的某个内存区域的指针。您可以在标准C库中看到这种方法的示例,其中包含文件访问函数,如
fopen()
,它返回指向文件类型的指针
虽然这实现了创建不透明类型的目标,但它需要API库来管理内存分配。因为它是指针,所以您可能会遇到内存被分配但从未释放的问题,或者尝试使用内存已被释放的指针的问题。这还意味着,专用硬件上的专用应用程序可能很难将功能移植到具有基本支持(不包括内存分配器)的专用传感器上。这种隐藏的开销也会影响资源有限的专用应用程序,并且能够预测或建模应用程序使用的资源
第二种方法是向API用户提供一个数据结构,该数据结构的大小与API使用的实际数据结构相同,但它使用一个字符缓冲区来分配内存。这种方法隐藏了内存布局的细节,因为API的所有用户看到的都是单个字符缓冲区或数组,但它也分配了API使用的正确内存量。然后,API拥有自己的结构,该结构展示了内存的实际使用方式,API在内部执行指针转换以更改用于访问内存的结构
第二种方法提供了几个好处。首先,API使用的内存现在由API的用户管理,而不是库本身。API的用户可以决定是否使用堆栈分配、全局静态分配或其他一些内存分配,如malloc()
。API的用户可以决定是否将内存分配封装在某种资源跟踪中,例如引用计数或用户希望自己进行的其他管理中(尽管也可以使用指针不透明类型)。这种方法还允许API用户更好地了解内存消耗
#define MY_THING_SIZE 256
typedef struct {
char array[MY_THING_SIZE];
} MyThing;
int DoMyThing (MyThing *pMyThing, int stuff);
typedef struct {
int thingyone;
int thingytwo;
char aszName[32];
} RealMyThing;
int DoMyThing (MyThing *pMyThing, int stuff)
{
RealMyThing *pReal = (RealMyThing *)pMyThing;
// do stuff with the real memory layout of MyThing
return 0;
}
typedef union
{
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
typedef union
{
#if __COMPILE_FOR_SYSTEM
struct __pthread_mutex_s
{
...internal struct member declarations...
} __data;
#endif
char __size[__SIZEOF_PTHREAD_MUTEX_T];
long int __align;
} pthread_mutex_t;
assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T);