Я изучаю разные версии реализации 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?
1. Различные программы, связанные с GLIBC, будут работать с одним и тем же shm, это вызывает проблемы, поэтому меня это волнует. 2. Когда вы вызываете pthread_rwlock_wrlock
, он устанавливает __readers
или __lock
Связь между двумя программами, связанными с glibc, по-прежнему осуществляется ядром, а не glibc.
Я имею в виду, что pthread_rwlock_t
реализованы по-разному в разных версиях GLIBC. Это полностью проблема GLIBC и не имеет ничего общего с ядром.
Да, и мой вопрос, почему вас это волнует? Вы намерены отправить pthread_rwlock_t
объект/память между двумя процессами, связанными с разными glibc? Не могли бы вы предоставить образец заявления?
Потому что это вызывает проблему, а точнее, взаимоблокировку, вызванную доступом к поврежденному pthread_rwlock_t
Я добился этого, статически связав LIBC. И этот вопрос является прекрасным примером того, ПОЧЕМУ ВЫ НЕ СТАТИЧЕСКИ СВЯЗЫВАЕТЕ GLIBC.
Это полностью проблема GLIBC и не имеет ничего общего с ядром. Нет, это ваша проблема. Вы решили статически связать две программы, которые должны взаимодействовать на двоичном уровне, с двумя разными версиями GLIBC. Вы: «Доктор, мне больно, когда я это делаю». Доктор: «Не делайте этого».
@AndrewHenle Я не думаю, что смогу избежать здесь статического связывания GLIBC, потому что я хочу собрать и запустить две программы на одном компьютере. Одна программа использует библиотеку (только с библиотекой .so) с GLIBC2.17, а другая использует GLIBC2.30. Конечно, я знаю, что статическое связывание GLIBC глупо, но есть ли другие варианты? Между тем, мы не можем использовать Docker.
Я до сих пор не понимаю, почему вам нужно статически связывать glibc. В частности, обратите внимание, что какой бы ни была эта загадочная разделяемая библиотека, которая управляет вашим принятием решений, вероятно, сама динамически связана с glibc (потому что это сама разделяемая библиотека).
Одна программа использует библиотеку (только с библиотекой .so) с GLIBC2.17. Кто пишет общий объект для распространения, который не совместим с более поздней версией libc.so
?!?!? Скажи мне, чтобы я мог занести этих болванов в черный список.
Привет, @JohnBollinger, может быть, ты видишь этот пост ? Это контекст, над которым я сейчас работаю.
- Почему 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 дают очень мало гарантий совместимости представления данных в памяти. Как правило, вы не можете полагаться на разные версии библиотеки для обеспечения интероперабельных представлений в памяти большинства других типов данных.
I achieved this by staticly linking GLIBC
Так зачем вам это?For example, if __readers is set to 2
Вы обращаетесь к внутренней структуре типаpthread_rwlock_t
или используете толькоpthread_rwlock_*
аксессоры? (Даже если вы используете, вы скомпоновали glibc статически. Так что… какое вам дело?)