El Servidor HTTP Apache es un programa modular en el que el
administrador puede elegir la funcionalidad a incluir en el
servidor seleccionando un conjunto de módulos. Los módulos serán compilados
como Objetos Dinámicos Compartidos (DSOs) que existen por separado del fichero
binario de
Alternativamente, los módulos se pueden compilar estáticamente en
el binario
Este documento describe cómo utilizar los módulos DSO, así como la teoría en la que se basan.
El soporte DSO para cargar módulos httpd individuales de Apache se basa
en un módulo llamado mod_foo.so
puede usar la httpd.conf
para cargar este módulo al iniciar el servidor
o al reiniciar.
Se pueden desactivar las construcciones DSO para módulos individuales con
la opción --enable-mods-static
tal y como se comenta en la documentación de instalación.
Para simplificar esta creación de archivos DSO para módulos httpd de Apache
(especialmente para módulos de terceros) un programa de apoyo
llamado make install
de
Para dar una visión general de las características DSO de Apache HTTP Server 2.x, aquí tenemos un resumen breve y conciso:
Build and install a distributed Apache httpd module, say
mod_foo.c
, into its own DSO
mod_foo.so
:
Configura Apache HTTP Server con todos los módulos habilitados. Solo unos
pocos de ellos se cargarán en el inicio del servidor. Se puede cambiar el conjunto
de módulos cargados activando o desactivando la directiva httpd.conf
.
Algunos módulos sólo son útiles para desarrolladores y no se generarán.
cuando se usa la opción de módulos all. Para generar todos los módulos
disponibles incluyendo los de desarrolladorhay que usar reallyall. Además
las directivas --enable-load-all-modules
.
mod_foo.c
, en su propio DSO mod_foo.so
fuera del árbol de código de Apache httpd usando En todos los casos, una vez se ha compilado el módulo compartido, se debe usar
una directiva httpd.conf
para indicarle a Apache httpd que active el módulo.
Ver la documentacióin apxs para más detalles.
En derivados modernos de Unix existe un mecanismo llamado enlace/carga dinámico de Objetos Dinámicos Compartidos (DSO) que facilita una forma de generar una parte de código de programa en un formato espacial para cargar en tiempo real en el espacio de direcciones de un programa ejecutable.
Esta carga generalmente se puede hacer de dos maneras:
automáticamente desde programa de sistema llamado ld.so
cuando se arranca un programa ejecutable o manualmente desde dentro
del programa que se ejecuta a través de un interfaz de sistema
programático del cargador de Unix a través de las llamadas de sistema
dlopen()/dlsym()
.
En la primera manera los DSO se llaman generalmente librerías
compartidas o librerías DSO y llamadas
libfoo.so
o libfoo.so.1.2
. Residen
en un directorio del sistema (generalmente /usr/lib
)
y el enlace con el programa ejecutable se establece en tiempo de
compilación especificando -lfoo
al comando enlazador.
Esto codifica de forma rígida referencias de librería en el fichero de
programa ejecutable de manera que en el arranque el cargador Unix es
capaz de localizar libfoo.so
en /usr/lib
, en
rutas con codificación rígida a través de opciones-de-enlazador como
-R
o en rutas configuradas por variables de entorno
LD_LIBRARY_PATH
. Entonces resuelve símbolos (todavía sin
uresolver) en el programa ejecutable que están disponibles en el DSO.
Los símbolos en el programa ejecutable no se referencian
generalmente por el DSO (porque es una biblioteca reutilizable de código
general) y, por lo tanto, no es necesario hacer más resolución. El programa
ejecutable no tiene necesidad de hacer nada por sí mismo para usar los
símbolos del DSO porque la resolución completa la realiza el cargador de
Unix. (De hecho, el código para invocar
ld.so
es parte del código de arranque en tiempo real que
se enlaza dentro de cada programa ejecutable que se ha generado como
no-estático). La ventaja de la carga dinámica de librerías de código común
es obvía: el código de librería necesita guardarse solo una vez,
en un sistema de librería como libc.so
, ahorrando espacio en
disco para cada programa.
En la segunda manera los DSO se llaman generalmente objetos
compartidos o ficheros DSO y pueden ser nombrados con una
extensión aribtraria (aunque el nombre canónico es foo.so
).
Estos ficheros generalmente permanencen dentro de un directorio de
programa específico y no hay enlace establecido automáticamente al
programaejecutable donde se están usando. En su lugar el programa ejecutable
carga manualmente el DSO en tiempo-real en su espacio de direcciones a
través de dlopen()
. En este momento no se realiza
resolución de símbolos del DSO para el programa ejecutable. Perp en
su lugar se resuelve automáticamente cualquier (todavía sin resolver)
símbolo en el DSO del conjunto de símbolos exportado por el programa
ejecutable y sus ya cargadas librerías DSO (especialmente todos los
símbolos del ubícuo libc.so
). De esta forma el DSO obtiene
conocimiento del símbolo del programa ejecutable como si hubiera servidor
enlazado estáticamente dentro de él mismo en primer lugar.
Por último, para aprovechar la API del DSO, el programa ejecutable
tiene que resolver determinados símbolos de la DSO a través de
dlsym()
para su uso posterior dentro de las tablas de envío
etc. En otras palabras: El programa ejecutable tiene que
resolver manualmente cada símbolo que necesita para poder utilizarlo.
La ventaja de este mecanismo es que no es necesario cargar las partes
opcionales del programa (y por lo tanto no gastan memoria) hasta que sean
necesarias para el programa en cuestión. Cuando se necesitan, estas partes
del programa se pueden cargar dinámicamente para ampliar la funcionalidad
del programa base.
Aunque este mecanismo DSO parece sencillo, hay al menos un paso difícil: La resolución de símbolos de del programa ejecutable para el DSO cuando se usa un DSO para extender un programa (la segunda manera). ¿Por qué? Porque la "resolución inversa" de símbolos DSO desde el conjunto de símbolos del programa ejecutable va en contra del diseño de la biblioteca (donde la biblioteca no tiene conocimiento de los programas que la utilizan) y no está disponible en todas las plataformas ni está estandarizada. En la práctica, los símbolos programa ejecutable a menudo no se reexportan y, por lo tanto, no están disponibles para su uso en un DSO. Encontrar una forma de forzar al enlazador a exportar todos los símbolos globales es el principal problema que uno tiene que resolver cuando se utiliza DSO para extender un programa en tiempo de ejecución.
El método de librería compartida es el típico, porque es para lo que se diseñó el mecanismo DSO, de ahí que se utilice para casi todos los tipos de librerías que el sistema operativo proporciona.
Las características anteriores basadas en DSO tienen las siguientes ventajas:
httpd.conf
en lugar de
opciones de apxs -i
seguido de un apachectl restart
para
traer una nueva versión de tu módulo recien desarrollado a un servidor
Apache HTTP que ya está funcionando.DSO tiene las siguientes desventajas:
ld -lfoo
) en todas las plataformas (por ejemplo las
plataformas basadas en a.out generalmente no proveen esta funcionalidad
mientras que las plataformas basadas en ELF si) no se puede usar el macanismo
DSO para todos los tipos de módulos. O en otras palabras, los módulos compilados
como ficheros DSO están restringidos a símbolos del núcleo de Apache httpd, de
la librería C (libc
) y todas las demás librerías estáticas o
dinámicas utilizadas por el nucleo de Apache httpd, o por los archivos de
librería estática (libfoo.a
) que contienen código independiente de
posición. Las únicas oportunidades de usar otro código es usar otro núcleo del
mismo httpd que previamente contenga una referencia a ellas o si carga el código
usted mismo a través de dlopen()
.