mirror of
https://github.com/apache/httpd.git
synced 2025-05-17 15:21:13 +03:00
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@87879 13f79535-47bb-0310-9956-ffa450edef68
395 lines
17 KiB
HTML
395 lines
17 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
<HTML><HEAD>
|
|
<TITLE>Apache 1.3 Dynamic Shared Object (DSO) support</TITLE>
|
|
</HEAD>
|
|
|
|
<!-- Background white, links blue (unvisited), navy (visited), red (active) -->
|
|
<BODY
|
|
BGCOLOR="#FFFFFF"
|
|
TEXT="#000000"
|
|
LINK="#0000FF"
|
|
VLINK="#000080"
|
|
ALINK="#FF0000"
|
|
>
|
|
<BLOCKQUOTE>
|
|
<!--#include virtual="header.html" -->
|
|
|
|
<DIV ALIGN=CENTER>
|
|
|
|
<H1>
|
|
Apache 1.3<BR>
|
|
Dynamic Shared Object (DSO)<BR>
|
|
Support
|
|
</H1>
|
|
|
|
<ADDRESS>Originally written by<BR>
|
|
Ralf S. Engelschall <rse@apache.org>, April 1998</ADDRESS>
|
|
|
|
</DIV>
|
|
|
|
<H3>Background</H3>
|
|
|
|
<P>On modern Unix derivatives there exists a nifty mechanism usually called
|
|
dynamic linking/loading of <EM>Dynamic Shared Objects</EM> (DSO) which
|
|
provides a way to build a piece of program code in a special format for
|
|
loading it at run-time into the address space of an executable program.
|
|
|
|
<P>This loading can usually be done in two ways: Automatically by a system
|
|
program called <CODE>ld.so</CODE> when an executable program is started or
|
|
manually from within the executing program via a programmatic system interface
|
|
to the Unix loader through the system calls <CODE>dlopen()/dlsym()</CODE>.
|
|
|
|
<P>In the first way the DSO's are usually called <EM>shared libraries</EM> or
|
|
<EM>DSO libraries</EM> and named <CODE>libfoo.so</CODE> or
|
|
<CODE>libfoo.so.1.2</CODE>. They reside in a system directory (usually
|
|
<CODE>/usr/lib</CODE>) and the link to the executable program is established
|
|
at build-time by specifying <CODE>-lfoo</CODE> to the linker command. This
|
|
hard-codes library references into the executable program file so that at
|
|
start-time the Unix loader is able to locate <CODE>libfoo.so</CODE> in
|
|
<CODE>/usr/lib</CODE>, in paths hard-coded via linker-options like
|
|
<CODE>-R</CODE> or in paths configured via the environment variable
|
|
<CODE>LD_LIBRARY_PATH</CODE>. It then resolves any (yet unresolved) symbols in
|
|
the executable program which are available in the DSO.
|
|
|
|
<P>Symbols in the executable program are usually not referenced by the DSO
|
|
(because it's a reusable library of general code) and hence no further
|
|
resolving has to be done. The executable program has no need to do anything on
|
|
its own to use the symbols from the DSO because the complete resolving is done
|
|
by the Unix loader. (In fact, the code to invoke <CODE>ld.so</CODE> is part of
|
|
the run-time startup code which is linked into every executable program which
|
|
has been bound non-static). The advantage of dynamic loading of common library
|
|
code is obvious: the library code needs to be stored only once, in a system
|
|
library like <CODE>libc.so</CODE>, saving disk space for every program.
|
|
|
|
<P>In the second way the DSO's are usually called <EM>shared objects</EM> or
|
|
<EM>DSO files</EM> and can be named with an arbitrary extension (although the
|
|
canonical name is <CODE>foo.so</CODE>). These files usually stay inside a
|
|
program-specific directory and there is no automatically established link to
|
|
the executable program where they are used. Instead the executable program
|
|
manually loads the DSO at run-time into its address space via
|
|
<CODE>dlopen()</CODE>. At this time no resolving of symbols from the DSO for
|
|
the executable program is done. But instead the Unix loader automatically
|
|
resolves any (yet unresolved) symbols in the DSO from the set of symbols
|
|
exported by the executable program and its already loaded DSO libraries
|
|
(especially all symbols from the ubiquitous <CODE>libc.so</CODE>). This way
|
|
the DSO gets knowledge of the executable program's symbol set as if it had
|
|
been statically linked with it in the first place.
|
|
|
|
<P>Finally, to take advantage of the DSO's API the executable program has to
|
|
resolve particular symbols from the DSO via <CODE>dlsym()</CODE> for later use
|
|
inside dispatch tables <EM>etc.</EM> In other words: The executable program has to
|
|
manually resolve every symbol it needs to be able to use it. The advantage of
|
|
such a mechanism is that optional program parts need not be loaded (and thus
|
|
do not spend memory) until they are needed by the program in question. When
|
|
required, these program parts can be loaded dynamically to extend the base
|
|
program's functionality.
|
|
|
|
<P>Although this DSO mechanism sounds straightforward there is at least one
|
|
difficult step here: The resolving of symbols from the executable program for
|
|
the DSO when using a DSO to extend a program (the second way). Why? Because
|
|
"reverse resolving" DSO symbols from the executable program's symbol set is
|
|
against the library design (where the library has no knowledge about the
|
|
programs it is used by) and is neither available under all platforms nor
|
|
standardized. In practice the executable program's global symbols are often
|
|
not re-exported and thus not available for use in a DSO. Finding a way to
|
|
force the linker to export all global symbols is the main problem one has to
|
|
solve when using DSO for extending a program at run-time.
|
|
|
|
<H3>Practical Usage</H3>
|
|
|
|
<P>The shared library approach is the typical one, because it is what the DSO
|
|
mechanism was designed for, hence it is used for nearly all types of libraries
|
|
the operating system provides. On the other hand using shared objects for
|
|
extending a program is not used by a lot of programs.
|
|
|
|
<P>As of 1998 there are only a few software packages available which use the
|
|
DSO mechanism to actually extend their functionality at run-time: Perl 5 (via
|
|
its XS mechanism and the DynaLoader module), Netscape Server, <EM>etc.</EM> Starting
|
|
with version 1.3, Apache joined the crew, because Apache already uses a module
|
|
concept to extend its functionality and internally uses a dispatch-list-based
|
|
approach to link external modules into the Apache core functionality. So,
|
|
Apache is really predestined for using DSO to load its modules at run-time.
|
|
|
|
<P>As of Apache 1.3, the configuration system supports two optional features
|
|
for taking advantage of the modular DSO approach: compilation of the Apache
|
|
core program into a DSO library for shared usage and compilation of the
|
|
Apache modules into DSO files for explicit loading at run-time.
|
|
|
|
<H3>Implementation</H3>
|
|
|
|
<P>The DSO support for loading individual Apache modules is based on a module
|
|
named <A HREF="mod/mod_so.html"><CODE>mod_so.c</CODE></A> which has to be
|
|
statically compiled into the Apache core. It is the only module besides
|
|
<CODE>http_core.c</CODE> which cannot be put into a DSO itself
|
|
(bootstrapping!). Practically all other distributed Apache modules then can
|
|
then be placed into a DSO by individually enabling the DSO build for them via
|
|
<CODE>configure</CODE>'s <CODE>--enable-shared</CODE> option (see top-level
|
|
<CODE>INSTALL</CODE> file) or by changing the <CODE>AddModule</CODE> command
|
|
in your <CODE>src/Configuration</CODE> into a <CODE>SharedModule</CODE>
|
|
command (see <CODE>src/INSTALL</CODE> file). After a module is compiled into
|
|
a DSO named <CODE>mod_foo.so</CODE> you can use <A
|
|
HREF="mod/mod_so.html"><CODE>mod_so</CODE></A>'s <A
|
|
HREF="mod/mod_so.html#loadmodule"><CODE>LoadModule</CODE></A> command in your
|
|
<CODE>httpd.conf</CODE> file to load this module at server startup or restart.
|
|
|
|
<P>To simplify this creation of DSO files for Apache modules
|
|
(especially for third-party modules) a new support program named <a
|
|
href="programs/apxs.html">apxs</a> (<EM>APache eXtenSion</EM>) is
|
|
available. It can be used to build DSO based modules <EM>outside
|
|
of</EM> the Apache source tree. The idea is simple: When installing
|
|
Apache the <CODE>configure</CODE>'s <CODE>make install</CODE>
|
|
procedure installs the Apache C header files and puts the
|
|
platform-dependent compiler and linker flags for building DSO files
|
|
into the <CODE>apxs</CODE> program. This way the user can use
|
|
<CODE>apxs</CODE> to compile his Apache module sources without the
|
|
Apache distribution source tree and without having to fiddle with the
|
|
platform-dependent compiler and linker flags for DSO support.
|
|
|
|
<P>To place the complete Apache core program into a DSO library (only required
|
|
on some of the supported platforms to force the linker to export the apache
|
|
core symbols -- a prerequisite for the DSO modularization) the rule
|
|
<CODE>SHARED_CORE</CODE> has to be enabled via <CODE>configure</CODE>'s
|
|
<CODE>--enable-rule=SHARED_CORE</CODE> option (see top-level
|
|
<CODE>INSTALL</CODE> file) or by changing the <CODE>Rule</CODE> command in
|
|
your <CODE>Configuration</CODE> file to <CODE>Rule SHARED_CORE=yes</CODE> (see
|
|
<CODE>src/INSTALL</CODE> file). The Apache core code is then placed into a DSO
|
|
library named <CODE>libhttpd.so</CODE>. Because one cannot link a DSO against
|
|
static libraries on all platforms, an additional executable program named
|
|
<CODE>libhttpd.ep</CODE> is created which both binds this static code and
|
|
provides a stub for the <CODE>main()</CODE> function. Finally the
|
|
<CODE>httpd</CODE> executable program itself is replaced by a bootstrapping
|
|
code which automatically makes sure the Unix loader is able to load and start
|
|
<CODE>libhttpd.ep</CODE> by providing the <CODE>LD_LIBRARY_PATH</CODE> to
|
|
<CODE>libhttpd.so</CODE>.
|
|
|
|
<H3>Supported Platforms</H3>
|
|
|
|
<P>Apache's <CODE>src/Configure</CODE> script currently has only limited but
|
|
adequate built-in knowledge on how to compile DSO files, because as already
|
|
mentioned this is heavily platform-dependent. Nevertheless all major Unix
|
|
platforms are supported. The definitive current state (May 1999) is this:
|
|
|
|
<P>
|
|
<UL>
|
|
<LI>Out-of-the-box supported platforms:<BR>
|
|
(actually tested versions in parenthesis)
|
|
|
|
<PRE>
|
|
o FreeBSD (2.1.5, 2.2.x, 3.x, 4.x)
|
|
o OpenBSD (2.x)
|
|
o NetBSD (1.3.1)
|
|
o BSDI (3.x, 4.x)
|
|
o Linux (Debian/1.3.1, RedHat/4.2)
|
|
o Solaris (2.4, 2.5, 2.6, 2.7)
|
|
o SunOS (4.1.3)
|
|
o Digital UNIX (4.0)
|
|
o IRIX (5.3, 6.2)
|
|
o HP/UX (10.20)
|
|
o UnixWare (2.01, 2.1.2)
|
|
o SCO (5.0.4)
|
|
o AIX (3.2, 4.1.5, 4.2, 4.3)
|
|
o ReliantUNIX/SINIX (5.43)
|
|
o SVR4 (-)
|
|
o Mac OS X Server (1.0)
|
|
o Mac OS (10.0 preview 1)
|
|
o OpenStep/Mach (4.2)
|
|
o DGUX (??)
|
|
o NetWare (5.1)
|
|
</PRE>
|
|
|
|
<P>
|
|
<LI> Explicitly unsupported platforms:
|
|
|
|
<PRE>
|
|
o Ultrix (no dlopen-style interface under this platform)
|
|
</PRE>
|
|
|
|
</UL>
|
|
|
|
<H3>Usage Summary</H3>
|
|
|
|
<P>To give you an overview of the DSO features of Apache 1.3, here is a short
|
|
and concise summary:
|
|
|
|
<OL>
|
|
|
|
<LI>Placing the Apache core code (all the stuff which usually forms the
|
|
<CODE>httpd</CODE> binary) into a DSO <CODE>libhttpd.so</CODE>, an executable
|
|
program <CODE>libhttpd.ep</CODE> and a bootstrapping executable program
|
|
<CODE>httpd</CODE> (Notice: this is only required on some of the supported
|
|
platforms to force the linker to export the Apache core symbols, which in turn
|
|
is a prerequisite for the DSO modularization):
|
|
|
|
<P>
|
|
<UL>
|
|
<LI>Build and install via <CODE>configure</CODE> (preferred):
|
|
<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD>
|
|
<PRE>
|
|
$ ./configure --prefix=/path/to/install
|
|
--enable-rule=SHARED_CORE ...
|
|
$ make install
|
|
</PRE>
|
|
</TD></TR></TABLE>
|
|
|
|
<LI>Build and install manually:
|
|
<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD>
|
|
<PRE>
|
|
- Edit src/Configuration:
|
|
<< Rule SHARED_CORE=default
|
|
>> Rule SHARED_CORE=yes
|
|
<< EXTRA_CFLAGS=
|
|
>> EXTRA_CFLAGS= -DSHARED_CORE_DIR=\"/path/to/install/modules\"
|
|
$ make
|
|
$ cp src/libhttpd.so* /path/to/install/modules/
|
|
$ cp src/libhttpd.ep /path/to/install/modules/
|
|
$ cp src/httpd /path/to/install/bin/
|
|
</PRE>
|
|
</TD></TR></TABLE>
|
|
</UL>
|
|
|
|
<LI>Build and install a <EM>distributed</EM> Apache module, say
|
|
<CODE>mod_foo.c</CODE>, into its own DSO <CODE>mod_foo.so</CODE>:
|
|
|
|
<P>
|
|
<UL>
|
|
<LI>Build and install via <CODE>configure</CODE> (preferred):
|
|
<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD>
|
|
<PRE>
|
|
$ ./configure --prefix=/path/to/install
|
|
--enable-shared=foo
|
|
$ make install
|
|
</PRE>
|
|
</TD></TR></TABLE>
|
|
|
|
<LI>Build and install manually:
|
|
<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD>
|
|
<PRE>
|
|
- Edit src/Configuration:
|
|
<< AddModule modules/xxxx/mod_foo.o
|
|
>> SharedModule modules/xxxx/mod_foo.so
|
|
$ make
|
|
$ cp src/xxxx/mod_foo.so /path/to/install/modules
|
|
- Edit /path/to/install/etc/httpd.conf
|
|
>> LoadModule foo_module /path/to/install/modules/mod_foo.so
|
|
</PRE>
|
|
</TD></TR></TABLE>
|
|
</UL>
|
|
|
|
<LI>Build and install a <EM>third-party</EM> Apache module, say
|
|
<CODE>mod_foo.c</CODE>, into its own DSO <CODE>mod_foo.so</CODE>
|
|
|
|
<P>
|
|
<UL>
|
|
<LI>Build and install via <CODE>configure</CODE> (preferred):
|
|
<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD>
|
|
<PRE>
|
|
$ ./configure --add-module=/path/to/3rdparty/mod_foo.c
|
|
--enable-shared=foo
|
|
$ make install
|
|
</PRE>
|
|
</TD></TR></TABLE>
|
|
|
|
<LI>Build and install manually:
|
|
<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD>
|
|
<PRE>
|
|
$ cp /path/to/3rdparty/mod_foo.c /path/to/apache-1.3/src/modules/extra/
|
|
- Edit src/Configuration:
|
|
>> SharedModule modules/extra/mod_foo.so
|
|
$ make
|
|
$ cp src/xxxx/mod_foo.so /path/to/install/modules
|
|
- Edit /path/to/install/etc/httpd.conf
|
|
>> LoadModule foo_module /path/to/install/modules/mod_foo.so
|
|
</PRE>
|
|
</TD></TR></TABLE>
|
|
</UL>
|
|
|
|
<P>
|
|
<LI>Build and install a <EM>third-party</EM> Apache module, say
|
|
<CODE>mod_foo.c</CODE>, into its own DSO <CODE>mod_foo.so</CODE> <EM>outside
|
|
of</EM> the Apache source tree:
|
|
|
|
<P>
|
|
<UL>
|
|
<LI>Build and install via <a href="programs/apxs.html">apxs</a>:
|
|
<TABLE BGCOLOR="#f0f0f0" CELLPADDING=10><TR><TD>
|
|
<PRE>
|
|
$ cd /path/to/3rdparty
|
|
$ apxs -c mod_foo.c
|
|
$ apxs -i -a -n foo mod_foo.so
|
|
</PRE>
|
|
</TD></TR></TABLE>
|
|
</UL>
|
|
|
|
</OL>
|
|
|
|
<H3>Advantages & Disadvantages</H3>
|
|
|
|
<P>The above DSO based features of Apache 1.3 have the following advantages:
|
|
|
|
<UL>
|
|
<LI> The server package is more flexible at run-time because the actual server
|
|
process can be assembled at run-time via <A
|
|
HREF="mod/mod_so.html#loadmodule"><CODE>LoadModule</CODE></A>
|
|
<CODE>httpd.conf</CODE> configuration commands instead of
|
|
<CODE>Configuration</CODE> <CODE>AddModule</CODE> commands at build-time.
|
|
For instance this way one is able to run different server instances
|
|
(standard & SSL version, minimalistic & powered up version
|
|
[mod_perl, PHP3], <EM>etc.</EM>) with only one Apache installation.
|
|
<P>
|
|
<LI> The server package can be easily extended with third-party modules even
|
|
after installation. This is at least a great benefit for vendor package
|
|
maintainers who can create a Apache core package and additional packages
|
|
containing extensions like PHP3, mod_perl, mod_fastcgi, <EM>etc.</EM>
|
|
<P>
|
|
<LI> Easier Apache module prototyping because with the DSO/<CODE>apxs</CODE>
|
|
pair you can both work outside the Apache source tree and only need an
|
|
<CODE>apxs -i</CODE> command followed by an <CODE>apachectl
|
|
restart</CODE> to bring a new version of your currently developed module
|
|
into the running Apache server.
|
|
</UL>
|
|
|
|
<P>DSO has the following disadvantages:
|
|
|
|
<UL>
|
|
<LI> The DSO mechanism cannot be used on every platform because not all
|
|
operating systems support dynamic loading of code into the address space
|
|
of a program.
|
|
<P>
|
|
<LI> The server is approximately 20% slower at startup time because of the
|
|
symbol resolving overhead the Unix loader now has to do.
|
|
<P>
|
|
<LI> The server is approximately 5% slower at execution time under some
|
|
platforms because position independent code (PIC) sometimes needs
|
|
complicated assembler tricks for relative addressing which are not
|
|
necessarily as fast as absolute addressing.
|
|
<P>
|
|
<LI> Because DSO modules cannot be linked against other DSO-based libraries
|
|
(<CODE>ld -lfoo</CODE>) on all platforms (for instance a.out-based
|
|
platforms usually don't provide this functionality while ELF-based
|
|
platforms do) you cannot use the DSO mechanism for all types of modules.
|
|
Or in other words, modules compiled as DSO files are restricted to only
|
|
use symbols from the Apache core, from the C library (<CODE>libc</CODE>)
|
|
and all other dynamic or static libraries used by the Apache core, or
|
|
from static library archives (<CODE>libfoo.a</CODE>) containing position
|
|
independent code. The only chances to use other code is to either make
|
|
sure the Apache core itself already contains a reference to it, loading
|
|
the code yourself via <CODE>dlopen()</CODE> or enabling the
|
|
<CODE>SHARED_CHAIN</CODE> rule while building Apache when your platform
|
|
supports linking DSO files against DSO libraries.
|
|
<P>
|
|
<LI> Under some platforms (many SVR4 systems) there is no way to force the
|
|
linker to export all global symbols for use in DSO's when linking the
|
|
Apache httpd executable program. But without the visibility of the Apache
|
|
core symbols no standard Apache module could be used as a DSO. The only
|
|
chance here is to use the <CODE>SHARED_CORE</CODE> feature because this
|
|
way the global symbols are forced to be exported. As a consequence the
|
|
Apache <CODE>src/Configure</CODE> script automatically enforces
|
|
<CODE>SHARED_CORE</CODE> on these platforms when DSO features are used in
|
|
the <CODE>Configuration</CODE> file or on the configure command line.
|
|
</UL>
|
|
|
|
<!--#include virtual="footer.html" -->
|
|
</BLOCKQUOTE>
|
|
</BODY>
|
|
</HTML>
|