Ваш вопрос путает виртуальный адрес с использованием адреса в качестве способа идентификации, поэтому первым шагом к пониманию является разделение понятий.
Рабочий пример - функция библиотеки времени выполнения C sprintf()
.При правильном объявлении и вызове он включается в программу как общий объектный модуль вместе со всеми необходимыми подфункциями.Адрес sprintf
варьируется от программы к программе, поскольку библиотека загружается по доступному свободному адресу.Для простой hello world программы sprintf может быть загружен по адресу 0x101000.Для сложной программы, которая рассчитывает налоги, она может быть загружена в 0x763f8000 (из-за всей противной логики, которую содержит основная программа, идет перед библиотеками, на которые она ссылается).С системной точки зрения разделяемая библиотека загружается в память только в одном месте, но адресное окно (диапазон адресов), которое каждый процесс видит, что память уникальна для этого исполняемого файла.
Конечно, это сложнодалее некоторые функции Security Enhanced Linux (SELinux) , которые рандомизируют адреса, по которым различные разделы программы загружаются в память, включая сопоставление с общей библиотекой.
--- уточнение -- Как правильно указывает кто-то, сопоставление виртуального адреса каждого процесса является специфическим для каждого процесса, мало чем отличается от его набора файловых дескрипторов, соединений с сокетами, родительских и дочерних процессов и т. Д. То есть p1 может сопоставлять адрес 0x1000 с физическим 0x710000, в то время какp2 сопоставляет адрес 0x1000 с ошибкой страницы, а p3 сопоставляется с некоторой общей библиотекой по физическому 0x9f32a000.Операционная система тщательно контролирует сопоставление виртуальных адресов, возможно, для обеспечения таких функций, как подкачка и подкачка страниц, а также для обеспечения таких функций, как общий код и данные, а также межпроцессные общие данные.