разделяемые библиотеки (dlopen) и поточная безопасность библиотечных статических указателей - PullRequest
1 голос
/ 02 марта 2012

Когда я загружаю разделяемую библиотеку динамически, например, с помощью dlopen в linux, мне нужно беспокоиться о видимости загруженной библиотеки между процессорами, или она будет автоматически ограждена / обеспечена безопасностью?

Например, скажем, у меня есть эта функция в загруженной библиотеке:

char const * get_string()
{  return "literal"; }

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

Скажите, что я загружаю библиотеку, а затем немедленно вызываю функцию get_string. Я передаю указатель на другой поток через атомарную последовательность, не связанную с памятью (смягчено на языке C ++ 11). Может ли другой поток безопасно использовать этот указатель без необходимости выполнять какие-либо ограничения нагрузки или другие инструкции синхронизации?

Я предполагаю, что это безопасно. Возможно, из-за того, что новая библиотека будет загружена на новые страницы, другое ядро ​​пока не может загрузить их, и, следовательно, не может иметь старой видимости на них?

Я бы хотел, чтобы какая-то авторская ссылка была частью ответа, если это возможно. Или техническое описание того, как это сделано потокобезопасным по умолчанию. Или, конечно, опровержение, если оно само по себе не является потокобезопасным.

Ответы [ 2 ]

1 голос
/ 04 марта 2012

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

Пользователи mmap обычно предполагают, что он правильно отобразит память на всех процессорах в точке ее возврата, так что видимость не имеет значения. Это не является явной гарантией, но ОС, вероятно, не сможет работать без такой гарантии. Также не существует известной системы, которая бы не работала, как ожидалось.

1 голос
/ 02 марта 2012

Ваш вопрос: dlopen() загрузит ли мой код lib должным образом перед возвратом? Да, это будет. В противном случае у вас возникла бы проблема только с одним потоком. Было бы очень трудно справиться, если бы вам пришлось спать до асинхронного завершения dlopen. Он также будет выполнять различные проверки и инициализировать то, что должно быть до того, как вы получите шанс получить искомый указатель на функцию. Это означает, что если вы получите этот указатель, все здесь, вы можете использовать напрямую в любом потоке.

Теперь, конечно, вам нужно передать этот указатель с обычной безопасностью потока, но я предполагаю, что вы знаете, как.

Обратите внимание, что статическая инициализация и модули не очень хорошо работают вместе (см. Все остальные вопросы по данной теме в SO).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...