[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: How does a shared library work?



Tshepang Lekhonkhobe wrote:
On 10/26/05, janne <jan.moren@lucs.lu.se> wrote:

ons 2005-10-26 klockan 10:18 +0200 skrev Tshepang Lekhonkhobe:

Hello,
I wanted to avoid some searching headache by asking this question here:
I hear that the advantage of shared libraries is that there's only one
copy of that library in memory and I assume that the library is loaded
in memory only the first moment that a dependant package is run. But
who's reponsible for making sure whose turn it is to use that library
in case of several dependant packages requiring its use? Is it the
kernel?

Neither. When you write something to be used as a shared library, it
needs to be written to be "reentrant". That means the library must be
able to have more than one process use it - even use the same exact code
- at the same time. That is not as big a headache as it sounds.

Remember that the code itself is never actually changed; it is in effect
a fixed text run by the processes (the same is true of just about any
code in fact). The problem is variables that do change, but that is
neatly solved by the memory controller:

Every process has its own mapped memory. This memory is divided into
text segments (the actual code) and data segments (room for variables,
stack and other data that changes as you run the application). When you
use the shared library, its code is mapped into the processes memory.
Note that it's not copied - there's still only one "real" copy - but the
memory controller effectively makes it seem it's part of the rest of the
program code.


Is the memory controller a part of the kernel?

The memory controller he's referring to is a part of the hardware.

The exact details depends on what hardware you run on. For the
x86 class machines, the memory controller is built into the
processor. On others there may be a separate Memory Management
Unit (MMU). The CPU deals in logical addresses, which are offsets
from the beginning of a selector, plus an indication of which
selector to use. The selector has attributes, known to the MMU
(told to the MMU by the OS) such as the start physical address,
size (usually in pages, which may be 256 bytes, or 4096 bytes,
or other sizes, depending on what exact hardware is, Pentium and
later x86 use 4096 bytes, IIRC), access modes (read, write, execute,
system only, etc.) which are permitted etc. When an access is made
to memory, the first check is whether the selector is initialized.
If not, then a General Protection Fault (GPF) is signaled.
Then the access mode is checked against the permissions. If this fails,
then a fault is generated. If we are ok so far, then the size is
checked, and if the access is beyond the end, then a fault is
generated. Otherwise, the base physical address of the selector
is added to the offset to get a physical address, and the access
takes places.

[At this point, more faults may be generated, like page not in
memory, which causes the OS to go look for a virtual page to
load. These faults are never passed on to the user, as they
are not "real" but are artifacts of the virtual memory system.
So I'm not considering them further.]

With Linux, all the possible faults get lumped together as
SIGSEGV, which the OS passes along as a signal. If the signal
is not caught, then the process is aborted and core is dumped.
If the signal is caught, then the signal handler tells the
OS what to do.

Except... if the fault occurs in OS code (I include device
drivers here) a panic results. This includes the scheduler,
interrupt handlers, etc.

Mike
--
p="p=%c%s%c;main(){printf(p,34,p,34);}";main(){printf(p,34,p,34);}
This message made from 100% recycled bits.
You have found the bank of Larn.
I can explain it for you, but I can't understand it for you.
I speak only for myself, and I am unanimous in that!



Reply to: