\appendix
\chapter{Funciones de la API de UNIX utilizadas}
 
Durante la programación del cliente y el servidor hemos utilizado APIs
o estructuras del sistema UNIX que pueden resultar poco familiares o
desconocidas, en este apartado vamos a explicar las más
importantes. Las vamos a separar en diferentes grupos en función de su
utilidad.
 
\section{Señales y tiempos} 
 
\subsection{signal} 
 
Para especificar qué tratamiento debe realiza un proceso al recibir
una señal, se emplea la llamada signal. Su declaración es la
siguiente:

\begin{verbatim}
#include <signal.h> 
 
void  *signal (int sig, void (*action) ()) (); 
 
\end{verbatim}

\begin{itemize}

\item sig es el número de la señal sobre la que queremos especificar la forma de tratamiento. 
\item action es la acción que queremos que se inicie cuando se reciba la señal. action puede tomar tres tipos de valores: 

\begin{itemize}

\item SIF\_DFL: Indica que la acción a realizar cuando se recibe la señal es la acción por defecto asociada a la señal. 
\item SIG\_IGN: Indica que la señal se debe ignorar. 
\item Dirección: Es la dirección de la rutina de tratamiento de la señal (manejador suministrado por el usuario). La declaración de esta función debe ajustarse al siguiente modelo. 
\end{itemize}
\end{itemize} 

\begin{verbatim}
#include <signal.h> 
 
void handler (sig [, code, scp]) 
int sig, code; 
struct sigcontext *scp; 

\end{verbatim} 
 
Cuando se recibe la señal sig, el núcleo es quien se encarga de llamar
a la rutina handler pasándole los parámetros sig, code y scp. sig es
el número de la señal, code es una palabra que contiene información
sobre el estado del hardware en el momento de invocar a handler y scp
contiene información de contexto definida en signal.h. Tanto code como
scp son parámetros opcionales y dependientes de la arquitectura de
nuestra máquina.
 
Un ejemplo de utilización de signal: 

\begin{verbatim} 
if (signal(SIGALRM, &ProcesoVisor) == SIG_ERR) { 
        fprintf(stderr,"No puedo registrar el 
        manejador de señales para SIGALRM\n"); 
} 
\end{verbatim}
 
\subsection{setitimer} 
 
Esta llamada se utiliza para controlar los temporizadores que hay
definidos por cada proceso. Su declaración es la siguiente:

\begin{verbatim} 
#include <time.h> 
 
setitimer (int which, struct itimerval *value, 
           struct itimerval *ovalue) 
 
\end{verbatim}

Los valores que puede tomar which son: 

\begin{itemize}
 
\item ITIMER\_REAL: Temporizador en tiempo real. 
\item ITIMER\_VIRTUAL: Temporizador en tiempo virtual. solamente contabiliza el tiempo mientras el proceso está ejecutando y no cuando duerme. 
\item ITIMER\_PROF: Temporizador de perfilado. Se usa al crear perfiles de un proceso. 
 
\end{itemize}

Setitimer se utiliza para definir el valor del temporizador
especificado por which. Value es un puntero a una estructura con los
nuevos valores del temporizador y ovalue es un puntero a una
estructura donde se devuelven los antiguos valores del temporizador.
 
La estructura itimerval se define como sigue: 

\begin{verbatim} 
struct itimerval 
{ 
        struct timeval it_interval; 
        struct timeval it_value; 
}; 
 
\end{verbatim}

siendo it\_interval el intervalo del temporizador y it\_value el valor actual del temporizador. 
 
 
La estructura timeval se define así: 

\begin{verbatim} 

struct timeval 
{ 
        unsigned long tv_sec; 
        long tv_usec; 
}; 

\end{verbatim}

siendo tv\_sec los segundos transcurridos desde el día 1 de Enero de
1970 y tv\_usec indica microsegundos. Su rango está comprendido entre
el 0 y 999.999.
 
 
Un ejemplo del uso de setitimer: 
 
\begin{verbatim}
 
itimer.it_interval.tv_usec =i_sec; 
itimer.it_interval.tv_sec = 0; 
 
itimer.it_value.tv_usec = i_sec; 
itimer.it_value.tv_sec = 0; 
 
setitimer(ITIMER_REAL, &itimer, NULL);

\end{verbatim}

\section{Regiones críticas o mutex}
 
Entre las funciones utilizadas tenemos: 
 
 
\subsection{pthread\_mutex\_init} 
 
Inicializa el semáforo para poder ser utilizado. POSIX define
distintos atributos que modifican el comportamiento de los
semáforos. Por defecto el mutex no utilizará ningún tipo de herencia
de prioridades.
 
Su definición es la siguiente: 

\begin{verbatim}
int pthread_mutex_init(pthread_mutex_t *mutex, 
        pthread_mutexattr_t *attr);
\end{verbatim}

Siendo mutex un puntero a un parámetro del tipo pthread\_mutex\_t, que
es el tipo de datos que usa la biblioteca Pthreads para controlar los
mutex. Attr es un puntero a una estructura del tipo
pthread\_mutexattr\_t, y sirve para definir qué tipo de mutex
queremos: normal, recursivo o errorcheck. Si este valor es NULL
(recomendado), la biblioteca le asignará un valor por defecto. La
función devuelve 0 si se pudo crear el mutex o -1 si hubo algún error.
 
 
\subsection{pthread\_mutex\_lock} 
 
Esta función pide el bloqueo para entrar en una RC (región
crítica). Si queremos implementar una RC, todos los threads tendrán
que pedir el bloqueo sobre el mismo semáforo. La definición es:
 
\begin{verbatim}
int pthread_mutex_lock(pthread_mutex_t *mutex);
\end{verbatim}

siendo mutex un puntero al mutex sobre el cual queremos pedir el
bloqueo o sobre el que nos bloquearemos en caso de que ya haya alguien
dentro de la RC. Como resultado, devuelve 0 si no hubo error, o
diferente de 0 si lo hubo.
 
\subsection{pthread\_mutex\_unlock} 
 
Esta es la función contraria a la anterior. Libera el bloqueo que
tuviéramos sobre un semáforo. La definición es:

\begin{verbatim} 
int pthread_mutex_unlock(pthread_mutex_t *mutex);
\end{verbatim}

siendo mutex el semáforo donde tenemos el bloqueo y queremos liberarlo.  
Retorna 0 como resultado si no hubo error o diferente de 0 si lo hubo. 

\section{Procesos}
 
\subsection{fork}
 
La única forma de crear un proceso en el sistema UNIX es mediante la
llamada fork. El proceso que invoca a fork se llama proceso padre y el
proceso creado es el proceso hijo. La declaración es la siguiente:
 
\begin{verbatim}
#include <sys/types.h> 
 
int fork(); 

\end{verbatim}

La llamada a fork hace que el proceso actual se duplique. A la salida
de fork, los dos procesos tienen una copia idéntica del contexto del
nivel de usuario excepto el valor de pid, que para el proceso padre
toma el valor del PID del proceso hijo y para el proceso hijo toma el
valor 0. Si la llamada a fork falla, devolverá el valor -1 y en errno
estará el código del error producido.


\section{Sockets}
 
\subsection{socket}
 
La llamada para abrir un canal bidireccional de comunicaciones es
socket y se declara como sigue:
 
\begin{verbatim}
#include <sys/types.h> 
#include <sys/socket.h> 
 
int socket (int af, int type, int protocol); 
 
\end{verbatim}

Socket crea un punto de conexión a un canal y devuelve un
descriptor. El descriptor del conector devuelto se usará en llamadas
posteriores a funciones de la interfaz.
 
Af (address family) especifica la familia de conectores o familia de
direcciones que se desea emplear. Las distintas familias están
definidas en el fichero de cabecera <sys/socket>. Las dos familias
siguientes suelen estar presentes en todos los sistemas:

\begin{itemize} 
\item AF\_UNIX: Protocolos internos UNIX. Es la familia de conectores empleada para comunicar procesos que se ejecutan en una misma máquina. 
\item AF\_INET: Protocolos Internet. Es la familia de conectores que se comunican mediante protocolos, tales como TCP o UDP. 
\end{itemize}
 
El argumento type indica la semántica de la comunicación para el
conector. Puede ser:

\begin{itemize}
\item SOCK\_STREAM: Conector con un protocolo orientado a conexión. 
\item SOCK\_DGRAM: Conector con un protocolo no orientado a conexión o datagrama. 
\end{itemize} 

Protocol especifica el protocolo particular que se va a usar con el
conector. Si la llamada se ejecuta satisfactoriamente, devolverá un
descriptor de fichero válido. En caso contrario, devolverá -1 y en
errno estará codificado el error producido.


\subsection{bind}
 
La llamada bind se utiliza para unir un conector con una dirección de
red y puerto determinados. Su declaración es la siguiente.
 
\begin{verbatim}
#include <sys/socket.h> 
/* Para familia AF_UNIX */ 
#include <sys/un.h> 
/* Para familia AF_INET */ 
#include <sys/netinet.h> 
 
int bind (int sfd, const void *addr, int addrlen); 
 
\end{verbatim}

Cuando se crea un conector con la llamada socket, se le asigna una
familia de direcciones, pero no una dirección particular. Bind hace
que el conector cuyo descriptor es sfd se una a la dirección de
conector especificada en la estructura apuntada por addr. Addrlen
indica el tamaño de la dirección.
 
\subsection{listen}
 
Cuando se abre un conector orientado a conexión, el programa servidor
indica que está disponible para recibir peticiones de conexión
mediante la llamada a listen, que se declara como sigue:
 
\begin{verbatim}
int listen (int sfd, int backlog);
\end{verbatim}

La llamada a listen la suele ejecutar el proceso servidor después de
las llamadas a socket y bind. Listen habilita una cola asociada al
conector descrito por sfd. La longitud de esta cola es la especificada
en el argumento backlog. Para que la llamada a listen tenga sentido,
el conector debe ser de tipo SOCK\_STREAM (orientado a conexión).
 
\subsection{connect}
 
Para que un proceso cliente inicie una conexión con un servidor a
través de un conector, es necesario que haga una llamada a
connect. Esta función se declara de la siguiente forma:
 
\begin{verbatim}
#include <sys/socket.h> 
/* familia AF_UNIX */ 
#include <sys/un.h> 
/* familia AF_INET */ 
#include <sys/netinet.h> 
 
int connect (int sfd, const void *addr, int addrlen); 
 
\end{verbatim}

sfd es el descriptor del conector que da acceso al canal y addr es un
puntero a una estructura que contiene la dirección del conector remoto
al que queremos conectarnos. Addrlen es el tamaño en bytes de la
dirección.
 
 
\subsection{accept}
 
Los procesos servidores van a leer peticiones de servicio mediante la
llamada accept. La declaración de esta llamada se muestra a
continuación:

\begin{verbatim}
#include <sys/socket.h> 
 
int accept (int sfd, void *addr, int *addrlen); 
 
\end{verbatim}

Esta llamada se usa con conectores orientados a conexión, como el tipo
SOCK\_STREAM. El argumento sfd es un descriptor del conector creado
por una llamada previa a socket y unido a una dirección mediante
bind. Accept extrae la primera petición de conexión que hay en la cola
de peticiones pendientes creada con una llamada previa a listen. El
argumento addr debe apuntar a una estructura local con la dirección
del conector. La llamada accept rellenará esa estructura con la
dirección del conector remoto que pide la conexión. El argumento
addrlen debe ser un puntero a int.
 
\subsection{close}
 
Una vez que un proceso no necesita realizar más accesos a un conector,
puede desconectarse del mismo. Para ello podemos usar la orden
close. Esta llamada va a cerrar el conector en sus dos sentidos.
 
 
\subsection{htonl}
 
Función que convierte datos unsigned long del formato que maneja el
ordenador al formato que maneja la red. La definición es:

\begin{verbatim}
unsigned long htonl (unsigned long hostlong); 
\end{verbatim}
 
\subsection{ntohl}
 
Función que convierte datos unsigned long del formato que maneja la
red al formato que maneja el ordenador. La definición es:

\begin{verbatim}
unsigned long ntohl (unsigned long netlong); 
\end{verbatim}

\subsection{select}
 
Permite interrogar al sistema sobre el estado de varios dispositivos y
devuelve cuáles están listos para leer datos de ellos y cuáles lo
están para escribir en ellos.
 
La declaración de select es la siguiente:

\begin{verbatim} 
#include <time.h> 
 
int select (int nfds, int readfds, int writefds, 
        int exceptfds, struct timeval *timeout);
\end{verbatim}

select examina los descriptores de fichero especificados en las
máscaras de bits readfds, writefds y exceptfds.
 
El significado de cada máscara es el siguiente:
 
\begin{itemize}
\item readfds representa los descriptores de los ficheros de lectura por los que preguntamos. 
\item writefds representa los descriptores de los ficheros de escritura que preguntamos. 
\item exceptfds representa los descriptores de los ficheros con alguna condición especial por los que preguntamos. 
\end{itemize}

Si alguna de las condiciones anteriores no nos interesa, lo
indicaremos pasándole a select el argumento 0.
 
Los argumentos se pasan por referencia, esto significa que select los
va a modificar de acuerdo con el estado de los ficheros que interroga.
timeout es un puntero no nulo que indica el tiempo máximo que se va a
esperar desde que select entra en ejecución hasta que devuelve el
control. Select puede devolver el control bien porque alguno de los
ficheros interrogados cumpla los requisitos pedidos o bien porque el
tiempo de espera especificado en timeout expire. Si timeout es un
puntero a NULL, la llamada esperará a que se dé algún cambio de estado
en alguno de los ficheros interrogados.
 
Las máscaras de bits que codifican los números de los descriptores
agrupan 32 posibles descriptores por cada numero entero. Si queremos
interrogar por ficheros con un descriptor más alto, hay que utilizar
un array de enteros. Para encapsular estos detalles, junto con select
se facilita un conjunto de 4 macros para manejar variables de ese
tipo.

 
Estas macros se definen con la siguiente interfaz:

\begin{itemize} 
\item FD\_ZERO (fd\_set *fdset): Pone a cero los bits de ``fdset''. 
\item FD\_SET (int fd, fd\_set *fdset): Activa en fdset el bit correspondiente al descriptor fd. 
\item FD\_CLEAR (int fd, fd\_set *fdset): Desactiva en fdset el bit correspondiente al descriptor fd. 
\item FD\_ISSET (int fd, fd\_set *fdset): Comprueba en fdset el bit correspondiente al descriptor fd.
\end{itemize}

\section{Memoria compartida}
 
\subsection{shmget}
 
Esta función devuelve el identificativo del segmento de memoria
compartida asociado al valor del argumento key. Su declaración es:
 
\begin{verbatim}

#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
 
int shmget (key_t key, int size, int shmflg); 

\end{verbatim}

siendo:
\begin{itemize} 
\item key es el identificativo del área de la memoria compartida.
\item size es el tamaño en bytes de la zona de memoria que queremos crear.
\item shmflg es una máscara de bits que está compuesta por los siguientes
valores:
 
\begin{itemize}
 
\item IPC\_CREAT: para crear un  nuevo segmento. Si este indicador no se usa, shmget() encontrará el segmento asociado con key, comprobará que el usuario tenga permiso para  recibir el shmid asociado con el segmento, y se asegurará de que el segmento no esté marcado para destrucción. 
\item IPC\_EXCL: Usado con IPC\_CREAT para asegurar el fallo si el segmento ya existe. 
Mode\_flags (9 bits mas bajos): Especifican los permisos otorgados al dueño, grupo y resto del mundo. 
\end{itemize}
 \end{itemize}
\subsection{shmat y shmdt} 
 
Antes de usar una zona de memoria compartida, tenemos que asignarle un
espacio de direcciones virtuales de nuestro proceso. Esto es lo que se
conoce como unirse o atarse al segmento de memoria compartida. Una vez
que dejamos de usar un segmento de memoria, tenemos que desatarnos de
él. Al realizar esta operación, el segmento deja de estar accesible
para el proceso. Sus definiciones son:

\begin{verbatim}
 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
 
char *shmat (int shmid, char *shmaddr, int shmflg); 
int shmdt (char *shmaddr); 
\end{verbatim}
 
siendo:
\begin{itemize}
\item shmid es el identificador de una zona de memoria creada mediante una llamada previa a shmget. 
\item shmaddr es la dirección virtual donde queremos que empiece la zona de memoria compartida.  
\item shmflg es una máscara de bits que indica la forma de acceso a la memoria. 
\end{itemize}
 
\subsection{shmctl} 
 

Con shmct realizamos operaciones de control sobre una zona de memoria
previamente creada por una llamada a shmget. Su declaración es:

\begin{verbatim} 
#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/shm.h> 
 
int shmctl (int shmid, int cmd, struct shmid_ds *buf) 
\end{verbatim}
 
shmid es un identificador válido devuelto por una llamada previa a
shmget.  cmd indica el tipo de operación a realizar. Entre las más
importantes está:

\begin{itemize} 
\item IPC\_RMID: Borra del sistema la zona de memoria compartida identificada por shmid. Si el segmento está unido a varios procesos, el borrado no se hace efectivo hasta que todos los procesos liberen la memoria.
\end{itemize}

\section{X Window}
 
\subsection{XOpenDisplay} 
 
Se usa para establecer una conexión entre un programa de aplicación y
un servidor de display. Su definición es:
 
\begin{verbatim}
Display *XOpenDisplay (char *nombreDisplay);
\end{verbatim}
Donde nombreDisplay es una cadena con el formato:
nombreHost:numero.numeroPantalla.
 
nombreHost es el nombre del host en el que reside el servidor. El
numero es el número del display, y el numeroPantalla es el numero de
la pantalla.
 
El nombreDisplay puede ser NULL, en cuyo caso se usará por la cadena
almacenada en la variable de entorno DISPLAY.
 
\subsection{XCloseDisplay}
 
Sirve para cerrar la conexión con el display. Su definición es la
siguiente:
 
\begin{verbatim}
XCloseDisplay (Display *display); 
\end{verbatim}
Cierra la conexión con el servidor de display especificado y destruye
todas las ventanas, todos los Ids de los recursos creados por el
programa.
 
\subsection{DefaultScreen}
 
Devuelve el número asociado a la pantalla por defecto en referencia a
un display abierto mediante XopenDisplay. Su definición es la
siguiente:

\begin{verbatim}
DefaultScreen (display); 
\end{verbatim}

Este número de pantalla se utilizará en llamadas a otras funciones,
por lo que es aconsejable que sea almacenado en una variable global.
 
\subsection{XCreateSimpleWindow}
 
Se utiliza para crear una ventana asociada a un display. Su definición
es la siguiente:

\begin{verbatim} 
Window XcreateSimpleWindow (Display *display, 
        Window madre, int x, int y, unsigned int anchura, 
        unsigned int altura, unsigned int anchuraborde, 
        unsigned long colorborde, unsigned long colorfondo);
\end{verbatim} 

El display especifica la conexión con el servidor. La madre especifica
la ventana madre donde se creará la ventana. Se pueden usar las macros
RootWindow o DefaultRootWindow.
 
\subsection{XMapWindow} 
 
Mapea la ventana especificada. Su definición es la siguiente: 
\begin{verbatim}
XmapWindow (Display *display, Window window); 
\end{verbatim} 

\subsection{XSelectInput} 
 
Durante la inicialización de nuestra aplicación y creación de la
ventana principal de la misma es necesario indicarle al servidor qué
tipo de eventos se desean recibir, pues puede interesarnos no recibir
información de algún tipo de evento ocurrido, mientras que otro pueda
ser vital para nuestra aplicación. Para la indicación de los eventos
deseados al servidor X se utiliza la función XselectInput y las
llamadas máscaras de eventos.
 
La definición de la función es la siguiente: 

\begin{verbatim} 
XselectInput (display, window, event_mask); 
\end{verbatim}

El argumento display es la variable que conecta nuestro cliente con el
servidor X, la variable window es el identificador de la ventana sobre
la que deseamos seleccionar los eventos que se recibirán, y
event\_mask es una variable máscara. Cada bit de esta variable se
refiere a un evento concreto. Para hacer más fácil la selección de
eventos se usan unas cadenas o nombres simbólicos que identifican a
los eventos.
 
Los principales son : ButtonPressMask, ButtonReleaseMask,
KeyPressMask, KeyReleaseMask, ButtonMotionMask, EnterWindowMask,
LeaveWindowMask, etc.
 
 
\subsection{XNextEvent} 
 
Recoge el siguiente evento de la cola en modo bloqueante, es decir,
recoge cualquier evento de cualquier ventana de nuestra aplicación y
lo introduce en la estructura XEvent que se le pasa como parámetro. Su
definición es la siguiente:

\begin{verbatim}
XNextEvent (Display *display, XEvent *evento); 
\end{verbatim}
La estructura XEvent es el paquete de información que el servidor
envía al cliente cuando ocurre el evento.
 
\subsection{XCreateGC} 
 
Un contexto gráfico o simplemente GC, es un recurso del servidor donde
se almacenan los atributos de los gráficos. Es necesario al menos un
GC para que el servidor acepte peticiones de primitivas gráficas por
parte del cliente, ya que cada petición de primitiva gráfica debe
especificar el identificador del GC que se debe usar.
 
Los GCs se crean y se almacenan en el servidor. Para pintar gráficos
es necesario:

\begin{itemize}
\item Crear un GC y obtener su ID.
\item Establecer los atributos del GC apropiadamente.  
\item Enviar las peticiones de las primitivas gráficas.
\end{itemize}

La definición para crear un contexto gráfico es la siguiente: 

\begin{verbatim} 
GC XcreateGC (Display *display, Drawable drw, 
        unsigned long mascara, XGCValues *valores);
\end{verbatim}

\subsection{XcopyArea}
 
La definición de esta función es la siguiente: 

\begin{verbatim}
XcopyArea (Display *display, drawable src, drawable dest, 
        GC gc, int src_x, int src_y, unsigned int width, 
        unsigned int height, int dest_x, int dest_y); 
\end{verbatim}

Esta función copia un área cuadrada desde el drawable src al drawable
dest. Ambos han de tener la misma profundidad de color.  La principal
ventaja de trabajar con estructuras XImage consiste en que éstas se
almacenan localmente en el cliente haciendo que no tengan que pasar
por la red.
% LocalWords:  API signal action SIF DFL SIG IGN sig handler scp setitimer PROF
% LocalWords:  which ITIMER Value ovalue itimerval it interval value timeval tv
% LocalWords:  sec usec mutex pthread init POSIX Pthreads Attr mutexattr NULL
% LocalWords:  errorcheck lock RC unlock fork pid errno Sockets socket Af sys
% LocalWords:  address family INET type SOCK DGRAM bind sfd addr Addrlen accept
% LocalWords:  backlog connect addrlen int close htonl unsigned long ntohl FD
% LocalWords:  select readfds writefds exceptfds timeout array fd set fdset key
% LocalWords:  CLEAR ISSET shmget identificativo size shmflg IPC CREAT shmid GC
% LocalWords:  EXCL Mode flags shmat shmdt shmaddr shmctl shmct cmd RMID Window
% LocalWords:  XOpenDisplay display nombreDisplay nombreHost host XCloseDisplay
% LocalWords:  numeroPantalla Ids DefaultScreen XopenDisplay RootWindow Mapea
% LocalWords:  XCreateSimpleWindow DefaultRootWindow XMapWindow XSelectInput
% LocalWords:  XselectInput window event mask ButtonPressMask ButtonReleaseMask
% LocalWords:  KeyPressMask KeyReleaseMask ButtonMotionMask EnterWindowMask GCs
% LocalWords:  LeaveWindowMask XNextEvent XEvent XCreateGC XcopyArea drawable
% LocalWords:  src dest XImage
