Я изучаю разные версии реализации 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;
Их реализации кажутся разными и вызывают у меня некоторые трудности. Потому что у меня есть программа a
, связанная с GLIBC2.30, и программа b
, связанная с GLIBC2.17. Обе программы будут работать с одним и тем же pthread_rwlock_t
, который используется в файле shm. Я добился этого, статически связав GLIBC.
Однако GLIBC2.30 и GLIBC2.17 будут интерпретировать объект pthread_rwlock_t
в shm по-разному, потому что их определения различаются. Например, если в GLIBC2.30 для __readers
установлено значение 2, а затем к нему обращается GLIBC2.17, он будет думать, что pthread_rwlock_t
заблокирован, и будет спать на этом. Однако pthread_rwlock_t
не заблокирован.
Мои вопросы:
pthread_rwlock_t
так сильно меняется среди версий? Это потому, что он хочет поддерживать больше функций или повышать производительность?ОБНОВЛЯТЬ
Я смотрю больше исходных кодов и нахожу:
lll_lock
для реализацииТогда у меня другой вопрос, разные версии GLIBC не совместимы друг с другом? Значит, я не могу использовать shm между разными версиями GLIBC?
🤔 А знаете ли вы, что...
C широко используется в разработке операционных систем, включая UNIX и Linux.
- Почему pthread_rwlock_t так сильно меняется между версиями? Это потому, что он хочет поддерживать больше функций или повышать производительность?
Потому что сопровождающие glibc решили, что от его изменения можно получить преимущество.
Как и в случае с большинством структур, определяемых стандартными заголовками, макет struct pthread_rwlock_t
не стандартизирован. Как и в некоторых подобных структурах, даже имена элементов не стандартизированы. Я предполагаю, что причина, по которой структура не является полностью непрозрачной, заключается в том, что экземпляры могут быть объявлены напрямую, вместо того, чтобы требовать их создания с помощью какой-либо функции-конструктора.
Вы идете на риск, если создаете программы, которые зависят от определенного макета этой структуры, за исключением той версии pthreads, для которой вы создаете. Это определение предоставляется версией pthreads.h
, используемой во время компиляции, и оно должно быть согласовано с соответствующей библиотекой.
- Могу ли я каким-либо образом использовать GLIBC2.30 и GLIBC2.17 с одним и тем же rwlock?
Думаю, вы уже знаете, что ответ «нет». Каждая реализация библиотеки имеет прямую зависимость от конкретного макета этой структуры, и макеты вообще не совпадают. Если вы хотите совместно использовать pthreads rwlock среди процессов, то, помимо настройки его атрибута pshared
, вы должны создавать взаимодействующие программы с одной и той же версией libpthread и ее заголовками (или любой другой библиотекой, обеспечивающей реализацию pthreads). Некоторый перекос версий может быть приемлемым на практике, но если вы хотите рискнуть этим, вам нужно протестировать и проверить определенные комбинации.
разные версии GLIBC несовместимы друг с другом?
Очевидно, что две версии, задействованные в вашей конкретной проблеме, несовместимы так, как вы надеялись. Glibc неплохо справляется с совместимостью ссылок:
программа, динамически связанная с одной версией, скорее всего, будет правильно взаимодействовать с разделяемыми библиотеками более поздних версий; и
программа, которая корректно компонуется и статически компонуется с одной версией, почти наверняка будет корректно компилироваться и статически компоноваться с более поздними версиями, вплоть до использования функций, удаленных из стандарта языка C (я смотрю на вас, gets()
).
Но нет ни требований, ни разумных ожиданий в отношении согласованных внутренних представлений большинства типов структур, предоставляемых библиотекой. Обратите внимание, что даже простое добавление членов, так что размер типа изменяется, приводит к несовместимому представлению.
Так что я нельзя использовать shm между разными версиями GLIBC?
Совместное использование памяти между программами, созданными для разных версий Glibc, вероятно, может быть успешно выполнено с типами данных, которые полностью определены вами на основе встроенных типов данных языка C (int
, double
и т. д.) и типов со стандартизированными представлениями (int32_t
, и т. д.). В принципе, однако, даже представления встроенных типов данных могут меняться между версиями.
Я предполагаю, что могут быть библиотеки C, предназначенные для этой конкретной цели (хотя я не знаю ни одной), но в целом реализации C дают очень мало гарантий совместимости представления данных в памяти. Как правило, вы не можете полагаться на разные версии библиотеки для обеспечения интероперабельных представлений в памяти большинства других типов данных.