Как два процесса могут совместно использовать одну общую библиотеку? - PullRequest
0 голосов
/ 29 октября 2018

Я пытался лучше понять, как работают разделяемые библиотеки, но я просто не могу разобраться с двумя вещами.

1- Каждый процесс имеет свое собственное пространство виртуальной памяти и таблицу страниц, поэтому если общая библиотека загружается в пространство виртуальной памяти одного процесса, то как второй процесс может получить доступ к этой общей библиотеке, поскольку она не находится в своем пространстве памяти?

2- Я понимаю, что только текстовый раздел является общим, а глобальные данные - нет, как это возможно? Насколько я понимаю, каждая ссылка на глобальную переменную осуществляется через GOT. Итак, если у меня есть эта строка кода x = glob, то она будет примерно равна примерно 1006 * в сборке, где ecx используется в качестве базового значения для GOT. Но если это так, то очевидно, что независимо от того, какой процесс вызывает эту строку, он всегда будет обращаться к одной и той же глобальной переменной, адрес которой по смещению 0x10 в GOT. Так как же два процесса могут иметь разные копии глобальной переменной, если они используют один и тот же текстовый раздел, который ссылается на одну и ту же запись GOT?

1 Ответ

0 голосов
/ 31 октября 2018

Предположительно, вы понимаете таблицы страниц и семантику копирования при записи.

Предположим, вы запускаете исполняемый файл a.out, который инициализирует некоторые глобальные данные, а затем fork() s. У вас не должно возникнуть проблем с пониманием того, что все доступные только для чтения (например, кодовые) страницы a.out теперь совместно используются двумя процессами ( точно такие же страницы физической памяти mmap записываются в обе виртуальные памяти пространства).

Теперь предположим, что a.out также использовал libc.so.6 до fork ing. У вас не должно возникнуть проблем с пониманием того, что страницы только для чтения, принадлежащие libc.so.6, также распределяются между процессами точно таким же образом.

Теперь предположим, что у вас есть два отдельных исполняемых файла a.out и b.out, каждый из которых использует libc.so.6. Предположим, что a.out запускается первым. Динамический загрузчик выполнит сопоставление только для чтения libc.so.6 в a.out пространство виртуальной памяти, и теперь некоторые его страницы находятся в физической памяти. В этот момент запускается b.out, и динамический загрузчик mmap возвращает те же libc.so.6 страницы в свою виртуальную память. Поскольку ядро ​​уже имеет сопоставление для этих страниц, у ядра нет причин создавать новые физические страницы для хранения сопоставления - оно может повторно использовать ранее отображенные физические страницы. Конечный результат такой же, как для двоичного файла fork - одни и те же физические страницы совместно используются между несколькими пространствами виртуальной памяти (и несколькими процессами).

Так как два процесса могут иметь разные копии глобальной переменной,

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

...