为什么 `pthread_rwlock_t` 的 ABI 在不同版本之间差异很大?
Why `pthread_rwlock_t`'s ABI differs a lot among versions?
我正在研究 pthread_rwlock_t
的不同实施版本。
GLIBC2.30
typedef union
{
struct __pthread_rwlock_arch_t __data;
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
long int __align;
} pthread_rwlock_t;
struct __pthread_rwlock_arch_t
{
unsigned int __readers;
unsigned int __writers;
unsigned int __wrphase_futex;
unsigned int __writers_futex;
unsigned int __pad3;
unsigned int __pad4;
...
GLIBC2.17
typedef union
{
# ifdef __x86_64__
struct
{
int __lock;
unsigned int __nr_readers;
unsigned int __readers_wakeup;
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
int __writer;
int __shared;
...
} pthread_rwlock_t;
他们的实现似乎不同,给我带来了一些困难。因为我有一个链接到 GLIBC2.30 的程序 a
和一个链接到 GLIBC2.17 的程序 b
。这两个程序将在 shm 上共享的相同 pthread_rwlock_t
上运行。我通过静态链接 GLIBC 实现了这一点。
然而,GLIBC2.30 和 GLIBC2.17 将以不同方式解释 shm 上的 pthread_rwlock_t
对象,因为它们的定义不同。例如,如果 __readers
被 GLIBC2.30 设置为 2 然后被 GLIBC2.17 访问,它会认为 pthread_rwlock_t
被锁定并睡眠。但是,pthread_rwlock_t
未锁定。
我的问题是:
- 为什么
pthread_rwlock_t
版本之间变化如此之大?是想支持更多功能,还是想提升性能?
- 有什么方法可以让 GLIBC2.30 和 GLIBC2.17 操作相同的 rwlock 吗?
更新
我查看了更多的源代码,发现:
- GLIBC2.17使用
lll_lock
实现
- GLIBC2.30使用原子操作哟实现
那我还有一个问题,不同版本的GLIBC是不是不能相互压缩?所以我不能在不同版本的 GLIBC 之间使用 shm?
- Why pthread_rwlock_t changes this much among versions? Is it because it want to support more features, or enhance performance?
因为 glibc 维护者认为更改它可以获得优势。
与标准 headers 定义的大多数结构一样,struct pthread_rwlock_t
的布局未标准化。对于一些这样的结构,甚至没有任何成员名称是标准化的。我认为结构不是完全不透明的原因是可以直接声明实例,而不是要求它们由某种构造函数生成。
如果您构建的程序依赖于该结构的特定布局,那么您将陷入困境,除非您构建的 pthreads 版本提供。 那个的定义是编译时使用的pthreads.h
的版本提供的,必须和对应的库匹配
- Is there any ways I can may GLIBC2.30 and GLIBC2.17 operate the same rwlock?
我想你已经知道答案是“不”了。每个库实现都直接依赖于该结构的特定布局,并且布局根本不一致。如果你想在进程之间共享一个 pthreads rwlock,那么除了配置它的 pshared
属性之外,你应该针对相同版本的 libpthread 及其 headers (或任何库提供你的pthreads 实现)。一些版本偏差在实践中可能是可以接受的,但如果你想冒险,那么测试和验证特定组合的责任就在你身上。
are different versions of GLIBC not compactible with each other?
很明显,您的特定问题涉及的两个版本与您希望的方式不兼容。 Glibc 在 link 兼容性方面相当不错:
针对一个版本动态 linked 的程序很可能与更高版本的共享库正确互操作;和
针对一个版本正确构建和静态 link 的程序几乎肯定会针对更高版本构建和静态 link 正确,甚至可以使用函数从 C 语言标准中删除(我在看着你,gets()
)。
但是对于库提供的大多数结构类型的一致内部表示没有要求,也没有合理的期望。请注意,即使只是添加成员,类型的大小也会发生变化,也会产生不兼容的表示形式。
So I
can't use shm between different versions of GLIBC?
在针对不同版本的 Glibc 构建的程序之间共享内存 可能 使用您根据 C 语言的 built-in 数据完全定义的数据类型成功完成类型(int
、double
、等。)和具有标准化表示的类型(int32_t
、等 .).然而,原则上,即使 built-in 数据类型的表示也可能在版本之间发生变化。
我想可能有专门为此明确目的而设计的 C 库(虽然我不知道),但一般来说,C 实现很少保证 in-memory 数据表示的兼容性。通常,您不能依赖库的不同版本来提供大多数其他数据类型的可互操作 in-memory 表示。
我正在研究 pthread_rwlock_t
的不同实施版本。
GLIBC2.30
typedef union { struct __pthread_rwlock_arch_t __data; char __size[__SIZEOF_PTHREAD_RWLOCK_T]; long int __align; } pthread_rwlock_t; struct __pthread_rwlock_arch_t { unsigned int __readers; unsigned int __writers; unsigned int __wrphase_futex; unsigned int __writers_futex; unsigned int __pad3; unsigned int __pad4; ...
GLIBC2.17
typedef union { # ifdef __x86_64__ struct { int __lock; unsigned int __nr_readers; unsigned int __readers_wakeup; unsigned int __writer_wakeup; unsigned int __nr_readers_queued; unsigned int __nr_writers_queued; int __writer; int __shared; ... } pthread_rwlock_t;
他们的实现似乎不同,给我带来了一些困难。因为我有一个链接到 GLIBC2.30 的程序 a
和一个链接到 GLIBC2.17 的程序 b
。这两个程序将在 shm 上共享的相同 pthread_rwlock_t
上运行。我通过静态链接 GLIBC 实现了这一点。
然而,GLIBC2.30 和 GLIBC2.17 将以不同方式解释 shm 上的 pthread_rwlock_t
对象,因为它们的定义不同。例如,如果 __readers
被 GLIBC2.30 设置为 2 然后被 GLIBC2.17 访问,它会认为 pthread_rwlock_t
被锁定并睡眠。但是,pthread_rwlock_t
未锁定。
我的问题是:
- 为什么
pthread_rwlock_t
版本之间变化如此之大?是想支持更多功能,还是想提升性能? - 有什么方法可以让 GLIBC2.30 和 GLIBC2.17 操作相同的 rwlock 吗?
更新
我查看了更多的源代码,发现:
- GLIBC2.17使用
lll_lock
实现 - GLIBC2.30使用原子操作哟实现
那我还有一个问题,不同版本的GLIBC是不是不能相互压缩?所以我不能在不同版本的 GLIBC 之间使用 shm?
- Why pthread_rwlock_t changes this much among versions? Is it because it want to support more features, or enhance performance?
因为 glibc 维护者认为更改它可以获得优势。
与标准 headers 定义的大多数结构一样,struct pthread_rwlock_t
的布局未标准化。对于一些这样的结构,甚至没有任何成员名称是标准化的。我认为结构不是完全不透明的原因是可以直接声明实例,而不是要求它们由某种构造函数生成。
如果您构建的程序依赖于该结构的特定布局,那么您将陷入困境,除非您构建的 pthreads 版本提供。 那个的定义是编译时使用的pthreads.h
的版本提供的,必须和对应的库匹配
- Is there any ways I can may GLIBC2.30 and GLIBC2.17 operate the same rwlock?
我想你已经知道答案是“不”了。每个库实现都直接依赖于该结构的特定布局,并且布局根本不一致。如果你想在进程之间共享一个 pthreads rwlock,那么除了配置它的 pshared
属性之外,你应该针对相同版本的 libpthread 及其 headers (或任何库提供你的pthreads 实现)。一些版本偏差在实践中可能是可以接受的,但如果你想冒险,那么测试和验证特定组合的责任就在你身上。
are different versions of GLIBC not compactible with each other?
很明显,您的特定问题涉及的两个版本与您希望的方式不兼容。 Glibc 在 link 兼容性方面相当不错:
针对一个版本动态 linked 的程序很可能与更高版本的共享库正确互操作;和
针对一个版本正确构建和静态 link 的程序几乎肯定会针对更高版本构建和静态 link 正确,甚至可以使用函数从 C 语言标准中删除(我在看着你,
gets()
)。
但是对于库提供的大多数结构类型的一致内部表示没有要求,也没有合理的期望。请注意,即使只是添加成员,类型的大小也会发生变化,也会产生不兼容的表示形式。
So I can't use shm between different versions of GLIBC?
在针对不同版本的 Glibc 构建的程序之间共享内存 可能 使用您根据 C 语言的 built-in 数据完全定义的数据类型成功完成类型(int
、double
、等。)和具有标准化表示的类型(int32_t
、等 .).然而,原则上,即使 built-in 数据类型的表示也可能在版本之间发生变化。
我想可能有专门为此明确目的而设计的 C 库(虽然我不知道),但一般来说,C 实现很少保证 in-memory 数据表示的兼容性。通常,您不能依赖库的不同版本来提供大多数其他数据类型的可互操作 in-memory 表示。