
% This is the standalone version of the paper

% Copyright (c)1994-1995, M. Welsh, mdw@cs.cornell.edu
% Unlimited distribution and modification of this work is permitted,
% as long as the original author is credited and the above copyright
% notice entact.

\chapter{\label{mdw}Conversi{\'o}n de Aplicaciones a Linux}
\author{Matt Welsh \\ {\tt mdw@cs.cornell.edu}}
\date{26 de Enero de 1995}

%
% Traducci{\'o}n de Ignacio Arenaza (inaki.arenaza@jet.es) para el proyecto
% LuCAS (http://www.infor.es/LuCAS/)
%
% $Id: porting.tex,v 1.2 1998/05/05 21:09:40 iarenaza Exp $
%
% $Log: porting.tex,v $
% Revision 1.2  1998/05/05 21:09:40  iarenaza
% Primera traducción. A revisar por el coordinador.
%
%

\section{Introducci{\'o}n}

La conversi{\'o}n de aplicaciones UNIX al sistema operativo Linux es
extremadamente f{\'a}cil. Linux, y la biblioteca GNU C usada por
{\'e}l, han sido dise{\~n}ados con la portabilidad de las aplicaciones
en mente, lo que significa que muchas aplicaciones compilar{\'a}n con
solo ejecutar {\tt make}. Aquellas que no lo hagan, generalmente
usar{\'a}n alguna caracter{\'\i}stica oscura de una implementaci{\'o}n
particular, o depender{\'a}n fuertemente del comportamiento
indocumentado o indefinido de, por ejemplo, una llamada particular del
sistema.

Linux obedece casi completamente el est{\'a}ndar IEEE 1003.1-1988
(POSIX.1), pero no ha sido certificado como tal. De igual forma, Linux
tambi{\'e}n implementa muchas de las caracter{\'\i}sticas que se
encuentran en las variantes SVID y BSD de UNIX, pero de nuevo no se
adhiere a ellas necesariamente en todos los casos. En general, Linux
ha sido dise{\~n}ado para ser compatible con otras implementaciones de
UNIX, para hacer la conversi{\'o}n de aplicaciones m{\'a}s f{\'a}cil,
y en ciertas ocasiones ha mejorado o corregido el comportamiento
encontrado en esas implementaciones.

Como ejemplo, el argumento {\em timeout\/} que se le pasa a la llamada
del sistema {\it select()\/} es realmente decrementado por Linux
durante la operaci{\'o}n de sondeo. Otras implementaciones no
modifican este valor para nada, y aquellas aplicaciones que no esperen
esto pueden dejar de funcionar cuando se compilen bajo Linux. Las
p{\'a}ginas del manual de BSD y SunOS para {\it select()\/} avisan de
que en una ``implementaci{\'o}n futura'', la llamada del sistema puede
modificar el puntero {\it timeout}. Desgraciadamente, muchas
aplicaciones todav{\'\i}a presuponen que el valor permanecer{\'a}
intacto.

El objetivo de este art{\'\i}culo es proporcionar una vista general de
los principales asuntos asociados a la conversi{\'o}n de aplicaciones
a Linux, resaltando las diferencias entre Linux, POSIX.1, SVID y BSD
en las siguientes {\'a}reas: gesti{\'o}n de se{\~n}ales, E/S de
terminales, control de procesos y obtenci{\'o}n de informaci{\'o}n y
compilaci{\'o}n portable condicional.

\section{Gesti{\'o}n de Se{\~n}ales}

A lo largo de los a{\~n}os la definici{\'o}n y sem{\'a}ntica de las
se{\~n}ales han sido modificadas de diferentes formas por diferentes
implementaciones de UNIX. Hoy en d{\'\i}a hay dos clases principales
de s{\'\i}mbolos: {\em no fiables\/} y {\em fiables}.  Las se{\~n}ales
no fiables son aquellas para las cuales el gestor de la se{\~n}al no
contin{\'u}a instalado una vez llamado. Esta se{\~n}ales
``mono-disparo'' deben reinstalar el gestor de la se{\~n}al dentro del
propio gestor de la se{\~n}al, si el programa desea que la se{\~n}al
siga instalada. A causa de esto, existe una condici{\'o}n de carrera
en la cual la se{\~n}al puede llegar de nuevo antes de que el gestor
este reinstalado, lo que puede hacer que, o bien la se{\~n}al se
pierda, o bien que se dispare el comportamiento original de la
se{\~n}al (tal como matar el proceso). Por lo tanto, estas se{\~n}ales
son ``no fiables'' puesto que la captura de la se{\~n}al y la
operaci{\'o}n de reinstalaci{\'o}n del gestor no son at{\'o}micas.

Con la sem{\'a}ntica de las se{\~n}ales no fiables, las llamadas del
sistema no son reiniciadas automaticamente cuando son interrumpidas
por una se{\~n}al. Por lo tanto, para que un programa tenga en cuenta
todas las posibilidades, es necesario que el programa compruebe el
valor de {\em errno\/} tras cada llamada del sistema, y reejecute la
llamada si su valor es {\em EINTR}.

De forma similar, la sem{\'a}ntica de las se{\~n}ales no fiables no
proporciona una forma f{\'a}cil de obtener una operaci{\'o}n de pausa
at{\'o}mica (poner un proceso a dormir hasta que llegue una
se{\~n}al). A causa de la naturaleza no fiable de la reinstalaci{\'o}n
de los gestores de se{\~n}ales, hay casos en los cuales la se{\~n}al
puede llegar sin que el programa se d{\'e} cuenta de ello.

Por otro lado, con la sem{\'a}ntica de las se{\~n}ales fiables, el
gestor de la se{\~n}al permanece instalado una vez llamado, y se evita
la condici{\'o}n de carrera. Tambi{\'e}n, ciertas llamadas del sistema
puede ser reiniciadas y es posible hacer una operaci{\'o}n de pausa
at{\'o}mica por medio de la funcion POSIX {\em sigsuspend\/}.

\subsection{Se{\~n}ales en SVR4, BSD, y POSIX.1}

La implementaci{\'o}n de se{\~n}ales SVR4 incorpora las funciones {\em
signal}, {\em sigset}, {\em sighold}, {\em sigrelse}, {\em sigignore}
y {\em sigpause}. La funci{\'o}n {\em signal\/} bajo SVR4 es
id{\'e}ntica a las cl{\'a}sicas se{\~n}ales UNIX V7, y proporciona
{\'u}nicamente se{\~n}ales no fiables. Las otras funciones s{\'\i}
proporcionan se{\~n}ales con reinstalaci{\'o}n autom{\'a}tica del
gestor de la se{\~n}al, pero no se soporta el reiniciado de las
se{\~n}ales del sistema.

Bajo BSD, se soportan las funciones {\em signal}, {\em sigvec}, {\em
sigblock}, {\em sigsetmask} y {\em sigpause}. Todas las funciones
proporcionan se{\~n}ales fiables con reiniciado de las llamadas del
sistema por defecto, pero dicho comportamiento puede ser inhabilitado
a voluntad por el programador.

Bajo POSIX.1 se proporcionan las funciones {\em sigaction}, {\em
sigprocmask}, {\em sigpending}, y {\em sigsuspend}.  N{\'o}tese que no
existe la funcion {\em signal} y que, de acuerdo con POSIX.1, debe
despreciarse. Estas funciones proporcionan se{\~n}ales fiables, pero
no se define el comportamiento de las llamadas del sistema. Si se usa
{\em sigaction} bajo SVR4 y BSD, el reiniciado de las llamadas del
sistema est{\'a} deshabilitado por defecto, pero puede activarse si se
especifica el flag de se{\~n}al {\tt SA\_RESTART}.

Por lo tanto, la ``mejor'' forma de usar las se{\~n}ales en un
programa es usar {\em sigaction}, que permite especificar
expl{\'\i}citamente el comportamiento de los gestores de
se{\~n}ales. Sin embargo, todav{\'\i}a hay muchas aplicaciones que
usan {\em signal}, y como podemos ver arriba, {\em signal} proporciona
sem{\'a}nticas diferentes bajo SV4R y BSD.

\subsection{Opciones de Se{\~n}ales en Linux}

En Linux se definen los siguiente valores para el miembro {\tt
sa\_flags} de la estructura {\tt sigaction}.

\begin{itemize}
\item {\tt SA\_NOCLDSTOP}: No enviar {\tt SIGCHLD} cuando un proceso
  hijo se detiene.
\item {\tt SA\_RESTART}: Forzar el reiniciado de ciertas llamadas del
  sistema cuando sean interrumpidan por un gestor de se{\~n}al.
\item {\tt SA\_NOMASK}: Deshabilitar la m{\'a}scara de se{\~n}ales
  (que bloquea las se{\~n}ales durante la ejecuci{\'o}n de un gestor
  de se{\~n}ales).
\item {\tt SA\_ONESHOT}: Eliminar el gestor de se{\~n}al tras la
  ejecuci{\'o}n. N{\'o}tese que SVR4 usa {\tt SA\_RESETHAND} para
  indicar lo mismo.
\item {\tt SA\_INTERRUPT}: Definido en Linux, pero no usado. Bajo
  SunOS, las llamadas del sistema se reiniciaban autom{\'a}ticamente, y
  este flag inhabilitaba ese comportamiento.
\item {\tt SA\_STACK}: Actualmente una operaci{\'o}n nula, a ser usada
  por las pilas de se{\~n}ales.
\end{itemize}

N{\'o}tese que POSIX.1 define {\'u}nicamente {\tt SA\_NOCLDSTOP}, y
que hay varias opciones m{\'a}s definidas por SVR4 que no est{\'a}n
disponibles en Linux. Cuando se porten aplicaciones que usen {\em
sigaction}, puede que necesite modificar los valores de {\tt
sa\_flags} para obtener el comportamiento apropiado.

\subsection{{\em signal\/} en Linux}

En Linux, la funci{\'o}n {\em signal\/} es equivalente a usar {\em
sigaction} con las opciones {\tt SA\_ONESHOT} y {\tt SA\_NOMASK}.
Esto es, corresponde a la sem{\'a}ntica cl{\'a}sica de se{\~n}ales no
fiables usada en SVR4.

Si desea que {\em signal} use la sem{\'a}ntica de BSD, la mayor{\'\i}a
de los sistemas Linux proporcionan una biblioteca de compatibilidad
BSD con la cual se puede enlazar. Para usar esta biblioteca,
deber{\'\i}a a{\~n}adir las opciones

\begin{verbatim}
  -I/usr/include/bsd -lbsd
\end{verbatim}
a la l{\'\i}nea de ordenes de compilaci{\'o}n. Cuando porte
aplicaciones que usen {\em signal}, preste mucha atenci{\'o}n a las
suposiciones que hace el programa sobre los gestores de se{\~n}ales y
modifique el codigo (o compile con las definiciones apropiadas) para
obtener el comportamiento adecuado.

\subsection{Se{\~n}ales soportadas por Linux}

Linux soporta casi todas las se{\~n}ales proporcionadas por SVR4, BSD y
POSIX, con algunas excepciones:
\begin{itemize}
\item {\tt SIGEMT} no est{\'a} soportada. Corresponde a un fallo de
  hardware en SVR4 y BSD.
\item {\tt SIGINFO} no est{\'a} soportada. Se usa para peticiones de
  informaci{\'o}n del teclado en SVR4.
\item {\tt SIGSYS} no est{\'a} soportada. Se refiere a una llamada del
  sistema no v{\'a}lida en SVR4 y BSD. Si enlaza con {\tt libbsd}, esta
  se{\~n}al se redefine como {\tt SIGUNUSED}.
\item {\tt SIGABRT} y {\tt SIGIOT} son id{\'e}nticas.
\item {\tt SIGIO}, {\tt SIGPOLL}, y {\tt SIGURG} son id{\'e}nticas.
\item {\tt SIGBUS} se define como {\tt SIGUNUSED}. T{\'e}cnicamente no existe
  un ``error de bus'' en el entorno Linux.
\end{itemize}

\section{E/S de Terminal}

Al igual que ocurre con las se{\~n}ales, el control de las E/S de
terminales tiene tres implementaciones diferentes: SVR4, BSD y
POSIX.1.

SVR4 usa la estructura {\tt termio} y varias llamadas {\em ioctl}
(tales como {\tt TCSETA}, {\tt TCGETA}, etc.) con un dispositivo de
terminal, para obtener y fijar los par{\'a}metros con la estructura
{\tt termio}. Esta estructura tiene la siguiente forma:

\begin{verbatim}
  struct termio {
    unsigned short c_iflag;  /* Modos de Entrada */
    unsigned short c_oflag;  /* Modos de Salida */
    unsigned short c_cflag;  /* Modos de Control*/
    unsigned short c_lflag;  /* Modos de Disciplina de L{\'\i}nea */
    char c_line;             /* Disciplina de L{\'\i}nea */
    unsigned char c_cc[NCC]; /* Caracteres de Control */
  };
\end{verbatim}

En BSD, se usa la estructura {\tt sgtty} junto con varias llamadas
{\em ioctl}, tales como {\tt TIOCGETP}, {\tt TIOCSETP}, etc.

En POSIX, se usa la estructura {\tt termios}, junto con varias
funciones definidas por POSIX.1, tales como {\em tcsetattr} and {\em
tcgetattr}. La estructura {\tt termios} es id{\'e}ntica a la
estructura {\tt struct termio} usada por SVR4, pero los tipos
est{\'a}n renombrados (como {\tt tcflag\_t} en vez de {\tt unsigned
short}) y se usa {\tt NCCS} para el tama{\~n}o del array {\tt c\_cc}.

En Linux, el nucleo soporta directamente tanto POSIX.1 {\em termios}
como SVR4 {\em termio}. Esto significa que si su programa usa uno de
estos dos m{\'e}todos para acceder a las E/S de terminal, deber{\'\i}a
compilar directamente en Linux. Si alguna vez est{\'a} en duda, es
f{\'a}cil modificar el c{\'o}digo que use {\tt termio} para usar {\tt
termios}, usando un peque{\~n}o conocimiento de ambos m{\'e}todos. Por
suerte esto nunca deber{\'\i}a ser necesario. Pero, si un programa
intenta usar el campo {\tt c\_line} de la estructura {\tt termio},
preste especial atenci{\'o}n. Para casi todas las aplicaciones, este
campo deber{\'\i}a ser {\tt N\_TTY}, y si el programa presupone que
est{\'a} disponible alg{\'u}n otro tipo de disciplina, puede que tenga
problemas.

Si su programa usa la implementaci{\'o}n BSD {\em sgtty}, puede
enlazar con {\tt libbsd.a} como se ha indicado anteriormente. Esto
proporciona un sustituto de {\em ioctl} que reenv{\'\i}a las
peticiones de E/S de terminal en t{\'e}rminos de las llamadas POSIX
{\tt termios} que usa el n{\'u}cleo. Cuando compile este tipo de
programas, si hay s{\'\i}mbolos indefinidos tales como {\tt TIOCGETP},
entonces necesitar{\'a} enlazar con {\tt libbsd}.

\section{Control e Informaci{\'o}n de Procesos}

Los programas como {\em ps}, {\em top} y {\em free} deben ser capaces
de obtener informaci{\'o}n del n{\'u}cleo sobre los procesos y recursos
del sistema. De forma similar, los depuradores y herramientas
similares necesitan ser capaces de controlar e inspeccionar un proceso
en ejecuci{\'o}n. Diferentes versiones de UNIX han proporcionado estas
caracter{\'\i}sticas a trav{\'e}s de interfaces diferentes, y casi todas
ellas son o bien dependientes de la m{\'a}quina o bien est{\'a}n
ligadas a un dise{\~n}o particular del n{\'u}cleo. Hasta ahora no ha
habido una interfaz aceptada universalmente para este tipo de
interacci{\'o}n n{\'u}cleo-proceso.

\subsection{Rutinas {\em kvm}}

Muchos sistemas usan rutinas tales como {\em kvm\_open}, {\em
kvm\_nlist} y {\em kvm\_read} para acceder directamente a las
estructuras de datos del n{\'u}cleo a trav{\'e}s del dispositivo {\em
/dev/kmem}. En general estos programas abrir{\'a}n {\em /dev/kmem},
leer{\'a}n la tabla de s{\'\i}mbolos del n{\'u}cleo, localizar{\'a}n los
datos del n{\'u}cleo en ejecuci{\'o}n con esta tabla y leer{\'a}n
las direcciones apropiadas en el espacio de direcciones del n{\'u}cleo
con estas rutinas. Puesto que esto requiere que el programa del
usuario y el n{\'u}cleo se pongan de acuerdo en cuanto al tama{\~n}o y
formato de las estructuras le{\'\i}das de esta forma, tales programas
deben ser reconstruidos para cada nueva revisi{\'o}n del n{\'u}cleo,
tipo de CPU, etc.

\subsection{{\em ptrace} y el sistema de ficheros {\em /proc}}

La llamada del sistema {\em ptrace} se usa en 4.3BSD y SVID para
controlar un proceso y leer informaci{\'o}n sobre {\'e}l. Normalmente la usan
los depuradores para, por ejemplo, detener la ejecuci{\'o}n de un proceso
en marcha y examinar su estado. En SVR4, {\em ptrace} ha sido
sustituida por el sistema de ficheros {\em /proc}, que se muestra como
un directorio que contiene una {\'u}nica entrada de fichero por cada
proceso en ejecuci{\'o}n y cuyo nombre es el ID del proceso. El programa
del usuario puede abrir el fichero correspondiente al proceso que le
interesa y generar varias llamadas {\em ioctl} sobre {\'e}l para controlar
su ejecuci{\'o}n u obtener informaci{\'o}n del n{\'u}cleo sobre el proceso. De
forma similar, el programa puede leer o escribir datos directamente en
el espacio de direcciones del proceso a trav{\'e}s del descriptor de
fichero del sistema de ficheros {\em /proc}.

\subsection{Control de Procesos en Linux}

En Linux se soporta la llamada del sistema {\em ptrace} para el control
de los procesos, y funciona como en 4.3BSD. Linux tambi{\'e}n
proporciona el sistema de ficheros {\em /proc} para obtener
informaci{\'o}n de los procesos y el sistema, pero con una
sem{\'a}ntica muy diferente. En Linux, {\em /proc} consta de una
serie de ficheros que proporcionan informaci{\'o}n general del sistema
tales como uso de memoria, media de carga, estad{\'\i}sticas de los
m{\'o}dulos cargados y estad{\'\i}sticas de la red. Se puede acceder a
estos ficheros usando {\em read} y {\em write} y se puede analizar su
contenido con {\em scanf}. El sistema de ficheros {\em /proc} de Linux
tambi{\'e}n proporciona un subdirectorio por cada proceso en
ejecuci{\'o}n, cuyo nombre es el ID del proceso. Este subdirectorio
contiene ficheros con informaciones tales como la l{\'\i}nea de
{\'o}rdenes, enlaces al directorio de trabajo actual y al fichero
ejecutable, descriptores de ficheros abiertos, etc. El n{\'u}cleo
proporciona toda esta informaci{\'o}n al vuelo en respuesta a las
peticiones de {\em read}. Esta implementaci{\'o}n no es muy diferente
del sistema de ficheros {\em /proc} disponible en Plan 9, pero tiene
sus inconvenientes---por ejemplo, para que una herramienta como {\em
ps} liste una tabla de informaci{\'o}n con todos los procesos en
ejecuci{\'o}n se debe recorrer un mont{\'o}n de directorios y abrir
y leer un mont{\'o}n de ficheros. En comparaci{\'o}n, las rutinas {\em
kvm} usadas por otros sistemas UNIX leen directamente las estructuras
de datos del n{\'u}cleo con s{\'o}lo unas pocas llamadas del sistema.

Obviamente, las diferencias de cada implementaci{\'o}n son tan abismales
que el convertir las aplicaciones que las usen puede ser una tarea de
titanes. Deber{\'\i}a resaltarse el hecho de que el sistema de ficheros
{\em /proc} de SVR4 es una bestia completamente diferente del sistema
de ficheros {\em /proc} que est{\'a} disponible en Linux y no pueden ser
usados en el mismo contexto. No obstante, se puede afirmar que
cualquier programa que use las rutinas {\em kvm} o el sistema de
ficheros {\em /proc} de SVR4 no es realmente portable y por tanto
dichas secciones de c{\'o}digo deben ser reescritas para cada sistema
operativo.

La llamada del sistema {\em ptrace} es casi id{\'e}ntica a la de BSD,
pero hay unas pocas diferencias:
\begin{itemize}
\item Las peticiones {\tt PTRACE\_PEEKUSER} y {\tt PTRACE\_POKEUSER}
 de BSD se denominan {\tt PTRACE\_PEEKUSR} y {\tt PTRACE\_POKEUSR},
 respectivamente, en Linux.
\item Se puede asignar valores a los registros usando la petici{\'o}n
 {\tt PTRACE\_POKEUSR} con los desplazamientos indicados en {\tt
 /usr/include/linux/ptrace.h}.
\item Las peticiones de SunOS {\tt PTRACE\_\{READ,WRITE\}\{TEXT,DATA\}}
 no est{\'a}n soportadas, como tampoco lo est{\'a}n {\tt
 PTRACE\_SETACBKPT}, {\tt PTRACE\_SETWRBKPT}, {\tt PTRACE\_CLRBKPT} o
 {\tt PTRACE\_DUMPCORE}.
 Las peticiones que faltan s{\'o}lo deber{\'\i}an afectar a un
 peque{\~n}o n{\'u}mero de programas existentes.
\end{itemize}

Linux {\em no} proporciona las rutinas {\em kvm} para la lectura del
espacio de direcciones del n{\'u}cleo desde un programa de usuario,
pero algunos programas (notablemente {\em kmem\_ps}) implementan sus
propias versiones de estas rutinas. En general, {\'e}stas no son
portables, y cualquier c{\'o}digo que use las rutinas {\em kvm}
probablemente depende de la disponibilidad de ciertos s{\'\i}mbolos o
estructuras de datos del n{\'u}cleo---una suposici{\'o}n poco
segura. El uso de las rutinas {\em kvm} deber{\'\i}a considerarse
espec{\'\i}fico de la arquitectura.

\section{Compilaci{\'o}n Condicional Portable}

Si necesita hacer modificaciones al c{\'o}digo existente para
convertirlo a Linux, puede que necesite usar pares {\tt ifdef}\ldots
{\tt endif} para rodear las partes del c{\'o}digo espec{\'\i}ficas de
Linux, o en general, del c{\'o}digo que correspoda a otras
implementaciones. No existe un est{\'a}ndar real para seleccionar
partes de c{\'o}digo a ser compiladas en funci{\'o}n del sistema
operativo, pero muchos programas usan la convenci{\'o}n de definir
{\tt SVR4} para el c{\'o}digo System V, {\tt BSD} para el c{\'o}digo
BSD y {\tt linux} para el c{\'o}digo espec{\'\i}fico de Linux.

La biblioteca GNU C usada por Linux le permite activar varias
caracter{\'\i}sticas de la misma definiendo ciertas macros en tiempo
de compilaci{\'o}n. Estas son:

\begin{itemize}
\item {\tt \_\_STRICT\_ANSI\_\_}: S{\'o}lo caracter{\'\i}sticas ANSI C.
\item {\tt \_POSIX\_SOURCE}: Caracter{\'\i}sticas POSIX.1.
\item {\tt \_POSIX\_C\_SOURCE}: Si definido a 1, caracter{\'\i}sticas
 POSIX.1. Si definido a 2, caracter{\'\i}sticas POSIX.2.
\item {\tt \_BSD\_SOURCE}: Caracter{\'\i}sticas ANSI, POSIX y BSD.
\item {\tt \_SVID\_SOURCE}: Caracter{\'\i}sticas ANSI, POSIX y System V.
\item {\tt \_GNU\_SOURCE}: ANSI, POSIX, BSD, SVID y extensiones GNU.
 Este es el valor por defecto si no se define ninguna de las
 anteriores.
\end{itemize}

Si usted define {\tt \_BSD\_SOURCE}, se definir{\'a} la definici{\'o}n
adicional {\tt \_FAVOR\_BSD} para la biblioteca. Esto har{\'a} que ciertas
cosas elijan el comportamiento BSD en lugar del comportamiento POSIX o
SVR4. Por ejemplo, si est{\'a} definido {\tt \_FAVOR\_BSD}, {\em setjmp} y
{\em longjmp} guardar{\'a}n y restaurar{\'a}n la m{\'a}scara de se{\~n}ales, y {\em
getpgrp} aceptar{\'a} un par{\'a}metro PID. Note que a pesar de todo, sigue
teniendo que enlazar con {\tt libbsd} para obtener el comportamiento
BSD en las caracter{\'\i}sticas mencionadas anteriormente en este
art{\'\i}culo.

En Linux, {\tt gcc} define un cierto n{\'u}mero de macros
autom{\'a}ticamente que usted puede utilizar en su programa. Estas
son:

\begin{itemize}
\item {\tt \_\_GNUC\_\_} (versi{\'o}n GNU C principal, p.ej., 2)
\item {\tt \_\_GNUC\_MINOR\_\_} (versi{\'o}n GNU C secundaria, p.ej., 5)
\item {\tt unix}
\item {\tt i386}
\item {\tt linux}
\item {\tt \_\_unix\_\_}
\item {\tt \_\_i386\_\_}
\item {\tt \_\_linux\_\_}
\item {\tt \_\_unix}
\item {\tt \_\_i386}
\item {\tt \_\_linux}
\end{itemize}

Muchos programas usan:

\begin{verbatim}
  #ifdef linux
\end{verbatim}

para rodear el c{\'o}digo espec{\'\i}fico de Linux. Usando estas
macros de tiempo de compilaci{\'o}n puede adaptar f{\'a}cilmente el
c{\'o}digo existente para incluir o excluir cambios necesarios para
portar el programa a Linux. N{\'o}tese que, puesto que Linux incorpora
en general m{\'a}s caracter{\'\i}sticas estilo System V, el mejor
c{\'o}digo base para comenzar con un programa escrito para System V y
BSD es probablemente la versi{\'o}n System V. De forma alternativa, se
puede partir de la base BSD y enlazar con {\tt libbsd}.

\section{Comentarios Adicionales} \footnote{A{\~n}adidos por Sven Goldt}

Este cap{\'\i}tulo cubre la mayor{\'\i}a de los asuntos relativos a la
conversi{\'o}n, excepto las llamadas del sistema que faltan y que se
indican en el cap{\'\i}tulo de llamadas del sistema, as{\'\i} como los
{\em streams\/} que a{\'u}n no existen (hay rumores de que
deber{\'\i}a existir un m{\'o}dulo cargable de {\em streams\/} en
ftp.uni-stutgart.de en /pub/systems/linux/isdn).

\endinput

%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:
