| <?xml version="1.0" encoding="UTF-8" ?> |
| <!DOCTYPE manualpage SYSTEM "./style/manualpage.dtd"> |
| <?xml-stylesheet type="text/xsl" href="./style/manual.es.xsl"?> |
| <!-- English Revision: 421174:587442 (outdated) --> |
| |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <manualpage metafile="dso.xml.meta"> |
| |
| <title>Soporte de Objetos Dinamicos Compartidos (DSO)</title> |
| |
| <summary> |
| <p>El servidor HTTP Apache es un programa modular en el que el |
| administrador puede elegir qué funcionalidades se incluyen |
| mediante la selección de un conjunto de módulos. En |
| primer lugar, los módulos pueden compilarse de manera |
| estática en el binario <program>httpd</program>. De forma |
| alternativa, los módulos también pueden compilarse como |
| Objetos Dinamicos Compartidos (DSOs) que existen de forma |
| independiente del archivo binario <program>httpd</program>. Los |
| módulos que se deseen usar como objetos dinámicos |
| compartidos pueden compilarse al mismo tiempo que el servidor, o |
| pueden compilarse en otro momento y ser añadidos después |
| usando la Herramienta de Extensión de Apache |
| (<program>apxs</program>).</p> |
| |
| <p>Este documento describe cómo usar los módulos en |
| forma de objeto dinámico compartido (DSO) así como los |
| fundamentos teóricos que hay detrás para explicar su |
| funcionamiento.</p> |
| </summary> |
| |
| |
| <section id="implementation"><title>Implementación</title> |
| |
| <related> |
| <modulelist> |
| <module>mod_so</module> |
| </modulelist> |
| <directivelist> |
| <directive module="mod_so">LoadModule</directive> |
| </directivelist> |
| </related> |
| |
| <p>Cargar módulos de Apache individualmente como objetos |
| dinámicos compartidos (DSO) es posible gracias a un |
| módulo llamado <module>mod_so</module> que debe compilarse |
| estáticamente en el núcleo (kernel) de Apache. Es el |
| único módulo junto con el módulo |
| <module>core</module> que no se puede usar como objeto |
| dinámico compartido. Prácticamente todos los demás |
| módulos distribuidos con Apache se pueden usar como objetos |
| dinámicos compartidos individualmente siempre y cuando se |
| haya activado la posibilidad de usarlos con la opción de |
| <program>configure</program> |
| <code>--enable-<em>module</em>=shared</code> tal y como se |
| explicó en la <a href="install.html">documentación de |
| instalación</a>. Una vez que haya compilado un módulo |
| como objeto dinámico compartido y le haya puesto un nombre |
| del tipo <code>mod_foo.so</code>, puede cargarlo al iniciar o |
| reiniciar el servidor usando el comando <directive |
| module="mod_so">LoadModule</directive> de <module>mod_so</module> |
| en el fichero <code>httpd.conf</code>.</p> |
| |
| <p>Para simplificar la creación de objetos dinámicos |
| compartidos para Apache (especialmente módulos de terceras |
| partes) está disponible un nuevo programa de soporte llamado |
| <program>apxs</program> (<em>APache eXtenSion</em>). Puede usar |
| este programa para crear módulos como objetos dinámicos |
| compartidos <em>sin tener que</em> crearlos al mismo tiempo que |
| compila su servidor Apache. La idea es simple: cuando se instala |
| Apache el procedimiento <code>make install</code> de |
| <program>configure</program> @@@ installs the Apache C header |
| files and puts the platform-dependent compiler and linker flags |
| for building DSO files into the apxs program / instala los |
| ficheros de cabecera de C de Apache y especifica las opciones de |
| compilación y enlace dependientes de la plataforma para |
| generar objetos dinámicos compartidos con |
| <program>apxs</program>. De esta manera el usuario puede usar |
| <program>apxs</program> para compilar el código fuente de |
| módulos de Apache de manera independiente y sin tener que |
| preocuparse por las opciones de compilación y enlace |
| dependientes de la plataforma que soportan objetos dinámicos |
| compartidos.</p> |
| |
| </section> |
| |
| <section id="usage"><title>Resumen de uso</title> |
| |
| <p>Para que se haga una idea de lo que permite el soporte de |
| objetos dinámicos compartidos en Apache 2.0, aquí tiene |
| un resumen breve pero conciso:</p> |
| |
| <ol> |
| <li> |
| Construir e instalar un módulo <em>incluido en la |
| distribución</em> de Apache, digamos |
| <code>mod_foo.c</code>, como un objeto dinámico |
| compartido de nombre <code>mod_foo.so</code>: |
| |
| <example> |
| $ ./configure --prefix=/path/to/install --enable-foo=shared<br /> |
| $ make install |
| </example> |
| </li> |
| |
| <li> |
| Construir e instalar un módulo de Apache de una |
| <em>tercera parte</em>, digamos <code>mod_foo.c</code>, como |
| un objeto dinámico compartido de nombre |
| <code>mod_foo.so</code>: |
| |
| <example> |
| $ ./configure --add-module=module_type:/path/to/3rdparty/mod_foo.c --enable-foo=shared<br /> |
| $ make install |
| </example> |
| </li> |
| |
| <li> |
| Configurar Apache para poder <em>instalar después</em> |
| objetos dinámicos compartidos: |
| |
| <example> |
| $ ./configure --enable-so<br /> |
| $ make install |
| </example> |
| </li> |
| |
| <li> |
| Construir e instalar un módulo de Apache de una |
| <em>tercera parte</em>, digamos <code>mod_foo.c</code>, como |
| un objeto dinámico compartido de nombre |
| <code>mod_foo.so</code> <em>fuera</em> de la estructura de |
| directorios de Apache usando <program>apxs</program>: |
| |
| <example> |
| $ cd /path/to/3rdparty<br /> |
| $ apxs -c mod_foo.c<br /> |
| $ apxs -i -a -n foo mod_foo.la |
| </example> |
| </li> |
| </ol> |
| |
| <p>En todos los casos, una vez que se compila el objeto |
| dinámico compartido, debe usar una directiva <directive |
| module="mod_so">LoadModule</directive> en |
| <code>httpd.conf</code> para activar dicho módulo.</p> |
| </section> |
| |
| <section id="background"><title>Fundamentos teoróricos |
| detrás de los objetos dinámicos compartidos</title> |
| |
| <p>En las versiones modernas de Unix, existe un mecanismo |
| especialmente útil normalmente llamado enlazado/carga de |
| <em>Objetos Dinámicos Compartidos</em> (DSO). Este mecanismo |
| ofrece una forma de construir trozos de código de programa en |
| un formato especial para cargarlo en tiempo de ejecución en |
| el espacio de direcciones de memoria de un programa |
| ejecutable.</p> |
| |
| <p>Esta carga puede hacerse de dos maneras: automáticamente |
| con un programa de sistema llamado <code>ld.so</code> al inicio de |
| un programa ejecutable o manualmente desde dentro del programa en |
| ejecución con una interfaz programática del sistema al |
| cargador de Unix mediante llamadas al sistema |
| <code>dlopen()/dlsym()</code>.</p> |
| |
| <p>Si se usa el primer método, los objetos dinámicos |
| compartidos se llaman normalmente <em>librerías |
| compartidas</em> ó <em>librerías DSO</em> y se |
| nombran como <code>libfoo.so</code> o |
| <code>libfoo.so.1.2</code>. Residen en un directorio de |
| sistema (normalmente <code>/usr/lib</code>) y el enlace con el |
| programa ejecutable se establece al construir la librería |
| especificando la opción<code>-lfoo</code> al comando de |
| enlace. Esto incluye las referencias literales a las |
| librerías en el programa ejecutable de manera que cuando |
| se inicie, el cargador de Unix será capaz de localizar |
| <code>libfoo.so</code> en <code>/usr/lib</code>, en rutas |
| referenciadas literalmente mediante opciones del linker como |
| <code>-R</code> o en rutas configuradas mediante la variable |
| de entorno <code>LD_LIBRARY_PATH</code>. Entonces se resuelven |
| los símbolos (todavía no resueltos) en el programa |
| ejecutable que están presentes en el objeto dinámico |
| compartido.</p> |
| |
| <p>Los símbolos en el programa ejecutable no están |
| referenciados normalmente en el objeto dinámico compartido |
| (porque son librerías reusables de propósito general) y |
| por tanto, no se producen más resoluciones. El programa |
| ejecutable no tiene que hacer nada por sí mismo para usar los |
| símbolos del objeto dinámico compartido porque todo el |
| trabajo de resolución lo hace @@@ Unix loader / el cargador |
| de Unix @@@. (De hecho, el código para invocar |
| <code>ld.so</code> es parte del código que se ejecuta al |
| iniciar, y que hay en cualquier programa ejecutable que haya sido |
| construido de forma no estática). La ventaja de cargar |
| dinámicamente el código de las librerías comunes es |
| obvia: el código de las librerías necesita ser almacenado |
| solamente una vez, en una librería de sistema como |
| <code>libc.so</code>, ahorrando así espacio en disco.</p> |
| |
| <p>Por otro lado, los objetos dinámicos compartidos |
| también suelen llamarse <em>objetos compatidos</em> o |
| <em>ficheros DSO</em> y se les puede nombrar con cualquier |
| extensión (aunque su nombre canónico es |
| <code>foo.so</code>). Estos archivos normalmente permanecen |
| dentro de un directorio específico del programa y no se |
| establecen enlaces automáticamente con los programas |
| ejecutables con los que se usan. En lugar de esto, el |
| programa ejecutable carga manualmente el objeto dinámico |
| compartido en tiempo de ejecución en su espacio de |
| direcciones de memoria con <code>dlopen()</code>. En ese |
| momento no se resuelven los símbolos del objeto |
| dinámico compartido para el programa ejecutable. En lugar |
| de esto, el cargador de Unix resuelve automáticamente los |
| símbolos (aún no resueltos en el objeto |
| dinámico compartido del conjunto de símbolos |
| exportados por el programa ejecutable y de las librerías |
| DSO que tenga ya cargadas (especialmente todos los |
| símbolos de la omnipresente <code>libc.so</code>). De |
| esta manera el objeto dinámico compartido puede conocer |
| el conjunto de símbolos del programa ejecutable como si |
| hubiera sido enlazado estáticamente en un primer |
| momento.</p> |
| |
| <p>Finalmente, para beneficiarse de la API de las DSOs, el |
| programa ejecutable tiene que resolver los símbolos |
| particulares de la DSO con <code>dlsym()</code> para ser usado |
| más tarde dentro de tablas de direccionamiento (dispatch |
| tables) <em>etc.</em> En otras palabras: El programa ejecutable |
| tiene que resolver manualmente cada uno de los símbolos que |
| necesita para poder usarlo después. La ventaja de ese |
| mecanismo es que las partes opcionales del programa no necesitan |
| ser cargadas (y por tanto no consumen memoria) hasta que se |
| necesitan por el programa en cuestión. Cuando es necesario, |
| estas partes del programa pueden cargarse dinámicamente para |
| expandir las funcionalidades básicas del programa.</p> |
| |
| <p>Aunque este mecanismo DSO parece muy claro, hay al menos un |
| paso de cierta dificultad: la resolución de los símbolos |
| que usa el programa ejecutable por la DSO cuando se usa una DSO |
| para extender la funcionalidad de una programa (segundo caso). Por |
| qué? Porque la resolución inversa de símbolos de |
| DSOs del conjunto de símbolos del programa ejecutable se hace |
| en contra del diseño de la librería (donde la |
| librería no tiene conocimiento sobre los programas que la |
| usan) y tampoco está disponible en todas las plataformas no |
| estandarizadas. En la práctica los símbolos globales del |
| programa ejecutable están disponibles para su uso en una |
| DSO. El mayor problema que hay que resolver cuando se usan DSOs |
| para extender un programa en tiempo de ejecución es encontrar |
| un modo de forzar al enlazador a exportar todos los símbolos |
| globales.</p> |
| |
| <p>El enfoque de las librerías compartidas es bastante |
| típico, porque es para lo que se diseño el mecanismo |
| DSO, por tanto se usa para casi todos los tipos de librerías |
| que incluye el sistema operativo. Por otro lado, no muchos |
| programas usan objetos compartidos para expandir sus |
| funcionalidades.</p> |
| |
| <p>En 1998, había solamente unos pocos programas disponibles |
| que usaban el mecanismo DSO para extender su funcionalidad en |
| tiempo de ejecucion: Perl 5 (por medio de su mecanismo XS y el |
| módulo DynaLoader), Netscape Server, <em>etc.</em> A partir |
| de la version 1.3, Apache se unió a este grupo, Apache usa |
| desde entonces una concepción modular para extender su |
| funcionalidad e internamente usa un enfoque de tablas de |
| direccionamiento (dispatch-list-based) para enlazar módulos |
| externos con las funcionalidades propias del servidor. De esta |
| manera, Apache puede usar el mecanismo DSO para cargar sus |
| módulos en tiempo de ejecución.</p> |
| </section> |
| |
| <section id="advantages"><title>Ventajas e Inconvenientes</title> |
| |
| <p>Las características de las librerías dinámicas |
| compartidas arriba explicadas tienen las siguientes ventajas:</p> |
| |
| <ul> |
| <li>El servidor es mucho más flexible en tiempo de |
| ejecución porque pueden añadirse módulos mediante |
| comandos de configuración <directive |
| module="mod_so">LoadModule</directive> en |
| <code>httpd.conf</code> en lugar de tener que hacerlo con las |
| opciones de <program>configure</program> al compilar. Por |
| ejemplo, de esta manera uno puede ejecutar diferentes instancias |
| del servidor (estándar & SSL, mínima & super |
| potente [mod_perl, PHP3], <em>etc.</em>) con una única |
| instalación de Apache.</li> |
| |
| <li>El servidor puede ser extendido fácilmente con |
| módulos de terceras partes después de la |
| instalación. Esto es un gran beneficio al menos para los |
| mantenedores de paquetes de distribuciones, que pueden crear un |
| paquete básico de Apache y paquetes adicionales que |
| contengan extensiones tales como PHP3, mod_perl, mod_fastcgi, |
| <em>etc.</em></li> |
| |
| <li>Facilita la labor de hacer prototipos de módulos de |
| Apache porque con el dúo DSO/<program>apxs</program> se |
| puede trabajar fuera de la estructura de directorios de Apache y |
| únicamente es necesario el comando <code>apxs -i</code> |
| seguido del comando <code>apachectl restart</code> para probar |
| la nueva versión del módulo que se está |
| desarrollando.</li> |
| </ul> |
| |
| <p>DSO presenta los siguientes inconvenientes:</p> |
| |
| <ul> |
| <li>El mecanismo DSO no puede ser usado en todas las plataformas |
| porque no todos los sistemas operativos soportan la carga |
| dinámica de código en el espacio de direcciones de |
| memoria de un programa.</li> |
| |
| <li>El servidor es aproximadamente un 20% más lento |
| iniciándose por la sobrecarga que implica la |
| resolución de símbolos por parte del cargador de Unix.</li> |
| |
| <li>El servidor es aproximadamente un 5% más lento |
| ejecutándose en algunas plataformas porque el código |
| posicionado independientemente (PIC) necesita algunas veces |
| procesos bastante complicados para calcular direcciones |
| relativas que no son en principio tan rápidos como los que |
| se usan para calcular direcciones absolutas.</li> |
| |
| <li>Como los módulos DSO no pueden enlazarse a otras |
| librerías basadas en DSO (<code>ld -lfoo</code>) en todas |
| las plataformas (por ejemplo en las plataformas basadas en a.out |
| normalmente no puede ser usada esta funcionalidad, mientras que |
| sí puede ser usada en las plataformas basadas en ELF) no se |
| puede usar el mecanismo DSO para todos los tipos de |
| módulos. En otras palabras, los módulos compilados |
| como ficheros DSO solamente pueden usar símbolos del |
| núcleo (kernel) de Apache, los de las librerías de C |
| (<code>libc</code>) y de todas las demas librerías |
| dinámicas o estáticas usadas por el núcleo de |
| Apache, o de archivos de librerías estáticas |
| (<code>libfoo.a</code>) que contengan código independiente |
| de su posición. Las únicas posibilidades para usar |
| otro código es asegurarse de que el núcleo de Apache |
| contiene una referencia a él o cargar el código por |
| medio de <code>dlopen()</code>.</li> |
| </ul> |
| |
| </section> |
| |
| </manualpage> |