Почему ABI pthread_rwlock_t сильно отличается в разных версиях?

Я изучаю разные версии реализации pthread_rwlock_t.

  1. 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;
      ...
    
  2. 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 не заблокирован.

Мои вопросы:

  1. Почему pthread_rwlock_t так сильно меняется среди версий? Это потому, что он хочет поддерживать больше функций или повышать производительность?
  2. Могу ли я каким-либо образом использовать GLIBC2.30 и GLIBC2.17 с одним и тем же rwlock?

ОБНОВЛЯТЬ

Я смотрю больше исходных кодов и нахожу:

  1. GLIBC2.17 использует lll_lock для реализации
  2. GLIBC2.30 использует атомарную операцию для реализации

Тогда у меня другой вопрос, разные версии GLIBC не совместимы друг с другом? Значит, я не могу использовать shm между разными версиями GLIBC?

I achieved this by staticly linking GLIBC Так зачем вам это? For example, if __readers is set to 2 Вы обращаетесь к внутренней структуре типа pthread_rwlock_t или используете только pthread_rwlock_* аксессоры? (Даже если вы используете, вы скомпоновали glibc статически. Так что… какое вам дело?)
KamilCuk 10.12.2020 13:33

1. Различные программы, связанные с GLIBC, будут работать с одним и тем же shm, это вызывает проблемы, поэтому меня это волнует. 2. Когда вы вызываете pthread_rwlock_wrlock, он устанавливает __readers или __lock

calvin 10.12.2020 13:35

Связь между двумя программами, связанными с glibc, по-прежнему осуществляется ядром, а не glibc.

KamilCuk 10.12.2020 13:35

Я имею в виду, что pthread_rwlock_t реализованы по-разному в разных версиях GLIBC. Это полностью проблема GLIBC и не имеет ничего общего с ядром.

calvin 10.12.2020 13:38

Да, и мой вопрос, почему вас это волнует? Вы намерены отправить pthread_rwlock_t объект/память между двумя процессами, связанными с разными glibc? Не могли бы вы предоставить образец заявления?

KamilCuk 10.12.2020 13:38

Потому что это вызывает проблему, а точнее, взаимоблокировку, вызванную доступом к поврежденному pthread_rwlock_t

calvin 10.12.2020 13:40

Я добился этого, статически связав LIBC. И этот вопрос является прекрасным примером того, ПОЧЕМУ ВЫ НЕ СТАТИЧЕСКИ СВЯЗЫВАЕТЕ GLIBC.

Andrew Henle 10.12.2020 13:40

Это полностью проблема GLIBC и не имеет ничего общего с ядром. Нет, это ваша проблема. Вы решили статически связать две программы, которые должны взаимодействовать на двоичном уровне, с двумя разными версиями GLIBC. Вы: «Доктор, мне больно, когда я это делаю». Доктор: «Не делайте этого».

Andrew Henle 10.12.2020 13:42

@AndrewHenle Я не думаю, что смогу избежать здесь статического связывания GLIBC, потому что я хочу собрать и запустить две программы на одном компьютере. Одна программа использует библиотеку (только с библиотекой .so) с GLIBC2.17, а другая использует GLIBC2.30. Конечно, я знаю, что статическое связывание GLIBC глупо, но есть ли другие варианты? Между тем, мы не можем использовать Docker.

calvin 10.12.2020 13:47

Я до сих пор не понимаю, почему вам нужно статически связывать glibc. В частности, обратите внимание, что какой бы ни была эта загадочная разделяемая библиотека, которая управляет вашим принятием решений, вероятно, сама динамически связана с glibc (потому что это сама разделяемая библиотека).

John Bollinger 10.12.2020 14:30

Одна программа использует библиотеку (только с библиотекой .so) с GLIBC2.17. Кто пишет общий объект для распространения, который не совместим с более поздней версией libc.so?!?!? Скажи мне, чтобы я мог занести этих болванов в черный список.

Andrew Henle 10.12.2020 14:32

Привет, @JohnBollinger, может быть, ты видишь этот пост ? Это контекст, над которым я сейчас работаю.

calvin 10.12.2020 14:33
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
12
163
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Почему pthread_rwlock_t так сильно меняется между версиями? Это потому, что он хочет поддерживать больше функций или повышать производительность?

Потому что сопровождающие glibc решили, что от его изменения можно получить преимущество.

Как и в случае с большинством структур, определяемых стандартными заголовками, макет struct pthread_rwlock_t не стандартизирован. Как и в некоторых подобных структурах, даже имена элементов не стандартизированы. Я предполагаю, что причина, по которой структура не является полностью непрозрачной, заключается в том, что экземпляры могут быть объявлены напрямую, вместо того, чтобы требовать их создания с помощью какой-либо функции-конструктора.

Вы идете на риск, если создаете программы, которые зависят от определенного макета этой структуры, за исключением той версии pthreads, для которой вы создаете. Это определение предоставляется версией pthreads.h, используемой во время компиляции, и оно должно быть согласовано с соответствующей библиотекой.

  1. Могу ли я каким-либо образом использовать GLIBC2.30 и GLIBC2.17 с одним и тем же rwlock?

Думаю, вы уже знаете, что ответ «нет». Каждая реализация библиотеки имеет прямую зависимость от конкретного макета этой структуры, и макеты вообще не совпадают. Если вы хотите совместно использовать pthreads rwlock среди процессов, то, помимо настройки его атрибута pshared, вы должны создавать взаимодействующие программы с одной и той же версией libpthread и ее заголовками (или любой другой библиотекой, обеспечивающей реализацию pthreads). Некоторый перекос версий может быть приемлемым на практике, но если вы хотите рискнуть этим, вам нужно протестировать и проверить определенные комбинации.

разные версии GLIBC несовместимы друг с другом?

Очевидно, что две версии, задействованные в вашей конкретной проблеме, несовместимы так, как вы надеялись. Glibc неплохо справляется с совместимостью ссылок:

  • программа, динамически связанная с одной версией, скорее всего, будет правильно взаимодействовать с разделяемыми библиотеками более поздних версий; и

  • программа, которая корректно компонуется и статически компонуется с одной версией, почти наверняка будет корректно компилироваться и статически компоноваться с более поздними версиями, вплоть до использования функций, удаленных из стандарта языка C (я смотрю на вас, gets()).

Но нет ни требований, ни разумных ожиданий в отношении согласованных внутренних представлений большинства типов структур, предоставляемых библиотекой. Обратите внимание, что даже простое добавление членов, так что размер типа изменяется, приводит к несовместимому представлению.

Так что я нельзя использовать shm между разными версиями GLIBC?

Совместное использование памяти между программами, созданными для разных версий Glibc, вероятно, может быть успешно выполнено с типами данных, которые полностью определены вами на основе встроенных типов данных языка C (int, double и т. д.) и типов со стандартизированными представлениями (int32_t, и т. д.). В принципе, однако, даже представления встроенных типов данных могут меняться между версиями.

Я предполагаю, что могут быть библиотеки C, предназначенные для этой конкретной цели (хотя я не знаю ни одной), но в целом реализации C дают очень мало гарантий совместимости представления данных в памяти. Как правило, вы не можете полагаться на разные версии библиотеки для обеспечения интероперабельных представлений в памяти большинства других типов данных.

Другие вопросы по теме