domingo, 16 de agosto de 2009

Bibliotecas en programas compilados en Linux


Cuando estamos programando bajo Linux y deseamos crear un programa ejecutable binario nativo (lo más probable en C o C++) necesitaremos usar algunas bibliotecas, por dos motivos. Algunas cosas son obligatorias y necesitan bibliotecas (para programar en C/C++ usamos siempre las libc, que son la implementación del estándar de C). Las bibliotecas son, en definitiva, otro pedazo de código binario que escribió una persona. La ventaja de usarlas es que no tenemos que escribir lo que ya esta escrito por nosotros mismos o otra persona.
Para compartir código binario (o sea, usarlo en otro programa) tenemos de dos posibilidades: hacer de él una biblioteca estática o una dinámica.
Cuando una biblioteca es estática, significa que , al vincular nuestros archivos objeto a ella, obtendremos un único binario, que contiene tanto el código de la aplicación como el de la biblioteca. Entonces, el compilador enlazará las llamadas a la biblioteca en llamadas dentro del mismo archivo, que será levantado como una pagina más del proceso que ejecute el programa. Además obtendremos un binario que puede ejecutarse en forma autónoma, con el costo de que sera mucho más grande.
Si utilizamos una biblioteca dinámica esto cambia drásticamente. La idea de usar una biblioteca compartida es, en principio, no tener su código dentro de nuestro binario. Por lo tanto, el compilador marcara en el que biblioteca necesita (con su versión) y donde se haga una referencia dentro de nuestro código, la dejara sin resolver. Esto es un enlace dinámico . Cuando el programa este en ejecución, el kernel se encargara de enlazar dinámicamente la llamada a la biblioteca con el código correspondiente.
Esto trae aparejada otra ventaja. Ya que la biblioteca no esta dentro del binario, sino aparte, puede ser utilizadas por dos programas en ejecución. Es decir, la biblioteca es también compartida, dado que dos aplicaciones pueden usar el mismo código y por ende, el sistema operativo solo debe cargarla y mantenerla en memoria una vez.
Una característica que nos ofrece el kernel es que nos permite cargar código en runtime. O sea, nos permite cargar código binario sin que sea enlazado dinámicamente, de esta manera, podemos realizar un programa con un plugins escrito en un lenguaje que se compile.