Si siente curiosidad por saber cómo funciona
la compatibilidad con Linux esta es la sección que
debe leer. La mayor parte de lo que sigue está
basado casi en su totalidad en un mensaje enviado por Terry
Lambert <tlambert@primenet.com>
a la lista lista de charla de FreeBSD
(Message ID: <199906020108.SAA07001@usr09.primenet.com>
).
FreeBSD dispone de una abstracció denominada “cargador de clase en ejecución”. Esto no es más que un bloque de código incrustado en la llamada execve(2) del sistema.
Históricamente las plataformas UNIX®
disponían de un único cargador
de binarios, que en última instancia
(fallback) recurría
al cargador #!
para ejecutar
cualesquiera intérpretes o scripts de la shell. Ese
cargador único examinaba el número
mágico (generalmente los 4 u 8 primeros bytes
del fichero) para ver si era un binario reconocible
por el sistema y, en tal caso, invocaba al cargador
binario.
Si no era de tipo binario, la llamada execve(2) devolvía un error y la shell intentaba empezar a ejecutarlo como órdenes shell, tomando por defecto como punto de partida “la shell actual, sea cual sea”.
Posteriormente se pensó en hacer una
modificación de manera que sh(1) examinara
los dos primeros caracteres, de modo que si eran
:\n
se llamaba a la shell
csh(1) en su lugar (parece ser que en SCO
fueron los primeros en utilizar ese truco).
Lo que ocurre ahora es que FreeBSD dispone de una
lista de cargadores, en lugar de uno solo. FreeBSD
recorre esa lista de cargadores, con un cargador genérico
#!
que sabe reconocer los
intérpretes en base a los caracteres que
siguen al siguiente espacio en blanco, con
/bin/sh
como último
recurso.
Para dar soporte a la ABI (“Application Binary Interface”) de Linux, FreeBSD interpreta el número mágico como un binario ELF (“Executable and Linking Format”): En este punto no hace distinción entre FreeBSD, Solaris™, Linux® o cualquier otro SO que tenga un tipo de imagen ELF.
El cargador ELF busca entonces una marca (brand) especial, una sección de comentarios en la imagen ELF que no está presente en los binarios ELF de SVR4/Solaris™.
Para que los binarios de Linux funcionen deben
estar marcados con brandelf(1) como tipo
Linux
:
#
brandelf -t Linux file
Hecho esto el cargador ELF verá la
marca Linux
en el fichero.
Cuando el cargador ELF ve la marca
Linux
sustituye un puntero en la
estructura proc
. Todas las
llamadas del sistema se indexan a través de
este puntero (en un sistema UNIX® tradicional
sería el «array» de estructura
sysent[]
que contiene las llamadas
del sistema). Además, el proceso se marca
con unos indicadores (“flags”) para que
el vector trampa del código de envío
señales lo maneje de una forma determinada,
así como otros arreglos (menores) que
serán utilizados por el módulo Linux
del kernel.
El vector de llamada del sistema Linux contiene,
entre otras cosas, una lista de entradas
sysent[]
cuyas direcciones residen
en el módulo del kernel.
Cuando el binario Linux realiza una llamada al
sistema, el código trampa extrae el puntero
a la función de la llamada del sistema de la estructura
proc
, y así obtiene los puntos de
entrada a las llamadas del sistema Linux, no las
de FreeBSD.
Además, el modo Linux cambia la raíz
de las búsquedas de una forma dinámica. En
efecto, esto es lo que hace la opción
union
cuando se monta un sistema de ficheros
(¡y que no es lo mismo que el
sistema de ficheros unionfs
!). Primero
se hace un intento de buscar el fichero en el directorio
/compat/linux/ruta-original
y solo después, si lo anterior
falla, se repite la búsqueda en el
directorio
/ruta-original
. Esto
permite que se puedan ejecutar binarios que necesitan de
otros binarios (por ejemplo las herramientas de
programación (“toolchain”) de Linux
pueden ejecutarse en su totalidad bajo la ABI de
Linux). Esto significa también que los binarios
Linux pueden cargar y ejecutar binarios FreeBSD si los binarios
Linux equivalentes no se hallan presentes y que se puede poner
una orden uname(1) en el árbol de directorios
/compat/linux
para poder estar seguros de
que los binarios Linux no puedan decir que no estaban
ejecutándose en Linux.
En efecto, hay un kernel Linux en el kernel
FreeBSD; las distintas funciones subyacentes que
implementan todos los servicios proporcionados
por el kernel son idénticas en ambas, las
tablas de entradas de llamadas del sistema en FreeBSD y en
Linux: operaciones del sistema de ficheros, operaciones
de memoria virtual, envío de señales
IPC System V, etc. La única diferencia es que
los binarios FreeBSD reciben sus funciones de
conexión (“glue”)
y los binarios Linux las suyas (la mayoría de los
sistemas operativos más antiguos solo tienen sus
propias funciones de conexión:
direcciones de funciones en un “array” de
estructura sysent[]
estática y
global, en lugar de direcciones de funciones que se extraen
a partir de un puntero inicializado dinámicamente
en la estructura proc
del proceso que hace
la llamada).
?Cuál es entonces la ABI nativa de FreeBSD? No importa. Básicamente, la única diferencia es (ahora mismo; esto podría cambiar y probablemente lo hará en una release futura) que las funciones de conexión de FreeBSD están enlazadas estáticamente en el kernel mientras que las de Linux pueden estarlo también estáticamente o se puede acceder a ellas por medio de un módulo del kernel.
Bien, pero ?de verdad es esto una emulación? No. Es una implementación ABI, no una emulación. No hay un emulador involucrado (ni un simulador, para adelantarnos a la siguiente pregunta).
Entonces ?por qué a veces se le llama “emulación Linux”? ¡Para hacer más difícil el vender FreeBSD! En serio, se debe a que la primera implementación se hizo en un momento en que realmente no había ninguna palabra distinta a esa para describir lo que se estaba haciendo; decir que FreeBSD ejecutaba binarios Linux no era cierto si no se compilaba el código o se cargaba un módulo; hacía falta una forma de describir todo esto y acabamos usando “emulador Linux”.
Puede descargar éste y muchos otros documentos desde ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/
Si tiene dudas sobre FreeBSD consulte la
documentación antes de escribir a la lista
<questions@FreeBSD.org>.
Envíe sus preguntas sobre la documentación a
<doc@FreeBSD.org>.