Está en la página 1de 48

SISTEMAS OPERATIVOS II

PROGRAMACIN CON LLAMADAS AL SISTEMA POSIX


(INTRODUCCIN A LA PROGRAMACIN CON UNIX /LINUX)

1- LLAMADAS AL SISTEMA :
1.1- Interfaz del programador:
La interfaz del sistema operativo con el programador es la que recupera los servicios y llamadas al sistema que los
usuarios pueden utilizar directamente desde sus programas. Esta es, quizs, una de las partes ms importante de un
sistema operativo, ya que recupera la visin que como mquina extendida tiene el usuario del sistema operativo. Las
interfaces ms utilizadas son: POSIX y Win32.

1.2- Concepto de llamada al sistema


La interfaz con el sistema operativo y los programas de usuario est definida por el conjunto de operaciones
extendidas que el sistema operativo ofrece. Estas instrucciones se han llamado tradicionalmente llamadas al
sistema, aunque ahora pueden implementarse de varias formas.
Para esconder realmente lo que los sistemas operativos hace, debemos examinar con detenimiento esta interfaz.
Las llamadas disponibles en la interfaz varan de un sistema operativo a otro (aunque los conceptos subyacentes
tienden a ser similares).
1.3- Implementacin:
Las llamadas al sistema se realizan de diversas formas de acuerdo a cada arquitectura de equipo. En una IBM
360/370 existe una llamada al sistema especial que hace un trap directamente al SO. Los 8 bits menos significativos
son un nmero que identifica el tipo de llamada. El CP/M no posee una instruccin de llamada al sistema especial: se
carga en el registro C el nmero de funcin y se realiza un salto a la direccin 5 de memoria.
A menudo se necesita pasar al SO informacin adicional al tipo de llamada al sistema. Por ejemplo, para leer una
imagen de entrada en tarjetas debemos especificar el archivo o dispositivo a usar y la direccin y longitud del buffer de
memoria del cual ser ledo. El dispositivo o archivo puede ya estar implcito en la llamada al sistema y como las
tarjetas tienen siempre 80 caracteres, podra no ser necesario el dato de longitud.
Dos mtodos generales son usados para pasar parmetros al SO, el ms simple es a travs de registros, y el otro,
a travs de bloques o tabla en memoria.

Las llamadas al sistema estn disponibles generalmente en assembler. La mayora de los sistemas permiten realizar
llamadas al sistema desde lenguajes de alto nivel (Pascal, Fortran, C, etc.), en los cuales una llamada realmente
involucra funciones predefinidas o llamadas a subrutinas. Ellas pueden generar una llamada a una rutina especial de
ejecucin que realiza una o varias llamada al sistema.
Algunos lenguajes como el C se han definido de forma tal de reemplazar el assembler por instrucciones de alto
nivel, permitiendo que las llamadas sean accedidas directamente.
Un ejemplo de cmo se usan las llamadas al sistema es considerar escribir un programa que lea datos de un
archivo y los copie a otro.
1) El programa necesita primeramente los nombres de los 2 archivos: el de entrada y el de salida. Esto puede
especificarse de 2 formas: que el programa pregunte al usuario los nombres, el cual en un sistema interactivo
requiere un secuencia de llamadas al sistema, primero para escribir la pregunta en la pantalla y luego para leer
lo que se contesta va teclado; en un sistema batch se especifican los nombres con tarjetas de control, en el
cual debe haber un mecanismo para pasar estos nombres al programa.
1 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
2) Luego se debe abrir el archivo de entrada y crear el de salida. Cada una de estas operaciones requiere
llamadas al sistema. Debe tambin preverse errores como la no existencia del archivo de entrada o la existencia
de proteccin de acceso al mismo.
(Se necesitan llamadas al sistema para manejar cada situacin).
3) Una vez abiertos los archivos, se entra en un loop de lectura que lee el archivo de entrada (una llamada al
sistema) y escribe sobre el de salida (otra llamada al sistema). Cada una de estas operaciones debe retornar
informacin sobre posibles errores. (Lectura: fin de archivo, error de paridad en la lectura; Escritura: sin
espacio en disco, fin de cinta fsico, impresora sin papel).
4) Luego de copiar todo el archivo, el programa debe cerrar los mismos (otra llamada al sistema), escribir un
mensaje en la consola (otra llamada) y terminar normalmente
Como vemos, los programas hacen uso intensivo de los servicios del SO: toda interaccin entre el programa y su
ambiente de trabajo lo realizan a travs de pedidos al SO. Sin embargo los usuarios, normalmente no alcanzan a ver
estos detalles.

1.4- Llamadas al sistemas en Linux:


Una llamada al sistema es normalmente una demanda al sistema operativo (ncleo) para que haga una operacin
de hardware/sistema especifica o privilegiada. Por ejemplo, en Linux-1.2, se han definido 140 llamadas al sistema. Las
llamadas al sistema como close() se implementan en la libc de Linux. Esta aplicacin a menudo implica la llamada a una
macro que puede llamar a syscall(). Los parmetros pasados a syscall() son el nmero de la llamada al sistema seguida
por el argumento necesario. Los nmeros de llamadas al sistema se pueden encontrar en <linux/unistd.h> mientras
que <s ys/syscall.h> actualiza con una nueva libc. Si aparecen nuevas llamadas que no tienen una referencia en libc
aun, puede usar syscall(). Como ejemplo, puede cerrar un fichero usando syscall() de la siguiente forma (no
aconsejable):
#include <syscall.h>
extern int syscall(int, ...);
int my_close(int filedescriptor)
{
return syscall(SYS_close, filedescriptor);
}
En la arquitectura i386, las llamadas al sistema estn limitadas a 5 argumentos adems del nmero de llamada al
sistema debido al nmero de registros del procesador. Si usa Linux en otra arquitectura puede comprobar el contenido
de <asm/unistd.h> para las macros syscall, para ver cuntos argumentos admite su hardware o cuantos escogieron los
desarrolladores.
Estas macros syscall se pueden usar en lugar de syscall(), pero esto no se recomienda ya que esa macro se
expande a una funcin que ya puede existir en una biblioteca. Por consiguiente, slo los desarrolladores del ncleo
deberan jugar a con las macros syscall. Como demostracin, aqu tenemos el ejemplo de close() usando una macro
syscall.
#include <linux/unistd.h>
_syscall1(int, close, int, filedescriptor);
La macro syscall1 expande la funcin close(). As tenemos close() dos veces, una vez en libc y otra vez en nuestro
programa. El valor devuelto por syscall() o un una macro syscall es -1 si la llamada al sistema fall y 0 en caso de xito.
Un vistazo a la variable global errno sirve para comprobar que ha ocurrido si la llamada al sistema fall.
Las siguiente llamadas al sistema estn disponibles en BSD y SYS-V pero no estn disponibles en Linux:
audit(), auditon(), auditsvc(), fchroot(), getauid(), getdents(), getmsg(),
2 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
mincore(), poll(), putmsg(), setaudit(), setauid().
1.5- POSIX:
POSIX (IEEE96) es un estndar de interfaz de sistemas operativos portables basado en el sistema operativo UNIX.
Aunque UNIX era prcticamente un estndar industrial, haba bastantes diferencias entre las distintas implementaciones
de UNIX, lo que provocaba que las aplicaciones no se pudieran transportar fcilmente entre distintas plataformas UNIX.
Este problema motiv a los desarrolladores y usuarios a implementar un estndar internacional con el propsito de
conseguir la portabilidad de las aplicaciones en cuanto a cdigo fuente.
POSIX se ha desarrollado entro de la IEEE con la referencia 1003 y tambin est siendo desarrollado como estndar
internacional con la referencia ISO/IEC 9945.
POSIX es una familia de estndares en evolucin, cada uno de los cuales cubre diferentes aspectos de los sistemas
operativos.
POSIX es una interfaz ampliamente utilizada. Se encuentra disponible en todas las versiones de UNIX y Linux,
inclusive Windows NT ofrece un subsistema que permite programar aplicaciones POSIX.
POSIX en una especificacin estndar, no define una implementacin. Los distintos sistemas operativos pueden
ofrecer los servicios POSIX con diferentes implementaciones.
Caractersticas ms relevantes:

Algunos tipos de datos utilizados por las funciones no se definen como parte del estndar, pero se defiene
como parte de la implementacin.
Estos tipos se encuentran definidos en el archivo de cabecera
<sys/types.h>. Estos tipos acaban con el sufijo _t. Por ejemplo: uid_t, es un tipo que se emplea para
almacenar un identificador de usuario (UID).

Los nombres de las llamadas al sistemas en POSIX son en general cortos y con todas sus letras en minsculas.
Ejemplo: fork, close, read.

Las funciones, normalmente devuelven cero si se ejecutaron con xito, o 1 en caso de error. Cuando una
funcin devuelve 1, se almacena en una variable global, denominada errno, el cdigo de error. Este cdigo de
error es un valor entero. La variable errno se encuentra definida en el archivo de cabecera <errno.h>.

La mayora de los recursos gestionado por el sistema operativo se referencias mediante descriptores.
descriptor es un nmero entero mayor o igual que cero.

Un

3 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II

GESTIN DE P ROCESOS/T HREAD CON POSIX

1 - S ERVICIOS PARA LA GESTIN DE PROCESOS : (CARRETERO PEREZ )


1.1- Identificacin de procesos:
POSIX identifica cada proceso por medio de un entero nico denominado Identificador de Proceso (Process ID,
PID) de tipo pid_t.
a- Obtener el identificador de un proceso:
pid_t getpid(void);
b- Obtener el identificador del proceso padre:
pid_t getppid(void)
Ejemplo:
#include <sys/types.h>
#include <stdio.h>
main(){
pid_t id_proceso;
pid_t id_padre;
id_proceso = getpid();
id_padre = getppid();
printf("Identificador de proceso: %d\n", id_proceso);
printf("Identificador del proceso padre %d\n", id_padre);
}
1.2- Entorno de un proceso:
Viene definido por una lista de variables que se pasan al mismo en el momento de comenzar su ejecucin. Estas
variables se denominan variables de entorno y son accesibles a un proceso a travs de la variable externa environ,
declarada de la siguiente forma.
extern char **environ;
Esta variable apunta a una lista de variables de entorno. Esta lista no es ms que un vector de punteros a cadenas
de caracteres de la forma nombre=valor, donde nombre hace referencia al nombre de una variable de entorno y valor
al contenido de la misma.
Ejemplo: Programa que imprime el entorno de un proceso
#include <stdio.h>
#include <stdlib.h>
extern char **environ;
int main(int argc, char **argv)
4 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
{
int i;
printf("Lista de variables de entorno de %s\n",argv[0]);
for (i=0 ; environ[i] != NULL ; i++)
printf("environ[%d] = %s\n", i, environ[i]);
}

Cada aplicacin interpreta la lista de variables de entorno de forma especfica. POSIX establece el significado de
determinadas variables de entorno:
HOME: directorio de trabajo inicial del usuario
LOGNAME: nombre del usuario asociado al un proceso
PATH: prefijo de directorios para encontrar ejecutables
TERM: tipo de terminal
TZ: informacin de la zona horaria
El servicio getenv permite buscar una determinada variable de entorno dentro de la lista de variables de entorno
de un proceso.
char *getenv(const char *name);
Esta funcin devuelve un puntero al valor asociado a la variable de entorno de nombre name. si la variable no se
encuentra definida, la funcin devuelve NULL.

Ejemplo: Programa que imprime el valor de la variable HOME


#include <stdio.h>
#include <stdlib.h>
int main(){
char *home = NULL;
home = getenv("HOME");
if (home == NULL)
printf("$HOME no se encuentra definida\n");
else
printf("El valor de $HOME es %s\n", home);
}
1.3- Creacin de procesos:
La nica forma es invocando la llamada al sistema fork. El SO realiza un clonacin del proceso que lo solicite. El
proceso que solicita el servicio se convierte en el proceso padre del nuevo proceso.
pid_t fork()
La clonacin se realiza copiando la imagen de memoria y la PCB. El proceso hijo es una copia del proceso padre en
el instante en que ste solicita al servicio fork. Esto significa que los datos y la pila del proceso hijo son los que tiene el
padre en ese instante de ejecucin. Es ms, dado que, al entrar el sistema operativo a tratar el servicio, lo primero que
5 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
hace es salva los registro en la PCB del padre, al copiarse la PCB se copian los valores salvado de los registro, por lo
que el hijo tiene los mismos valores que el padre.

Esto significa que el contador de programa de los dos procesos tiene el mismo valor, por lo que van a ejecutar la
misma instruccin mquina. No hay que caer en el error de pensar que el proceso hijo empieza la ejecucin del cdigo
en su punto de inicio, sino que el proceso hijo comienza a ejecutar, al igual que el padre, la sentencia que se encuentra
despus de fork().
Las diferencias que existen entre el proceso hijo y el padre son:

El proceso hijo tiene su propio identificador(PID).

El proceso hijo tiene una nueva descripcin de la memoria. Aunque el hijo tenga los segmentos con el
mismo contenido, no tienen por que esta en la misma zona de memoria.

El tiempo de ejecucin del proceso hijo es igual a cero.

Todas la alarmas pendientes se desactiva en el proceso hijo.

El conjunto de seales pendientes se pone en cero.

El valor que retorna el sistema operativo como resultado de fork() e distinto en el hijo que el padre (el hijo
recibe un 0 y el padre el PID del hijo).
Este valor de retorno se puede utilizar mediante una clusula de condicin para que le padre y el hijo sigan flujos
de ejecucin distintos.

Las modificaciones que realice el proceso padre sobre sus registros e imagen de memoria despus de fork no
afectan al hijo y, viceversa. Sin embargo, el proceso hijo tiene su propia copia de los descriptores del proceso padre.
6 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Esto hace que el hijo tenga acceso a los archivos abiertos por el proceso padre. El padre y el hijo comparte el puntero
de posicin de los archivos abiertos en el padre.
Ejemplo: Programa que crea un proceso
#include
#include
#include
#include

<sys/types.h>
<stdio.h>
<unistd.h>
<sys/wait.h>

int main(){
pid_t pid;
pid = fork();
if(pid==-1) /* error del fork() */
printf(Error\n);
else if(pid==0)
printf("Soy el HIJO, Proceso %d; padre = %d \n", getpid(), getppid());
else
printf("Soy el PADRE, Proceso %d\n", getpid());
}
// Ejemplo: Programa que crea una cadena de procesos
// En cada ejecucin del bucle crea un proceso. El proceso padre obtiene el
// identificador del hijo, que ser distinto de cero y saldr del bucle utilizando // la sentencia break. El proceso hijo
continuar la ejecucin, repitindose
// este proceso hasta que se llegue al final del bucle
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
int i;
int n = 10;
for (i = 0; i < n; i++){
pid = fork();
if (pid != 0)
break;
}
printf("El padre del proceso %d es %d\n", getpid(), getppid());
}

7 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
1.4- Ejecutar un programa:
El servicio exec de POSIX tiene por objetivo cambiar el programa (el cdigo) que se est ejecutado. Se puede
considerar que el servicio tiene dos fases. En la primera se vaca el proceso de casi todo su contenido, mientras en la
segunda se carga un nuevo programa.
exec no genera ningn proceso nuevo, simplemente cambia el programa que ejecuta el proceso que lo invoc.
En el proceso de vaciado de la imagen de memoria se conservan algunos datos como ser:

Entorno del proceso que el SO lo incluye en la nueva pila.

Ciertos datos de la PCB (PID, PPID, identificador de usuario y descriptores de archivos abiertos).
Fase de carga:

Asignar al proceso un nuevo espacio de memoria.

Cargar el texto y los datos iniciales en los segmentos correspondientes.

Crear la pila inicial del proceso con el entorno y los parmetros que se pasa al programa.

Llenar la PCB con los valores iniciales de los registro y la descripcin de los nuevo segmentos de memoria.

Prototipos de la familia de funciones exec:


int excl(char *path, char *arg, ...);
int execv(char *path, char *arg[]);
int execle(char *path, char *arg, ...);
int execve(char *path, char *arg[], char *envp[]);
int execlp(char *file, const char *arg, );
int execvp(char *file, char *argv[]);
La nueva imagen se construye a partir de un archivo ejecutable. Si la llamada se ejecuta con xito, sta no
devolver ningn valor puesto que la imagen del proceso habr sido reemplazada, caso contrario devuelve 1.
La funcin main() del nuevo programa tendr la forma:
int main(int argc, char **argv)
8 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
donde argc representa el nmero de argumentos que se pasan al programa, incluido el propio nombre del programa, y
argv es un vector de cadenas de caracteres, conteniendo cada elemento de este vector un argumento pasado al
programa. El primer componente de este vector (argv[0]) representa el nombre del programa.
Argumentos:
path: apunta al nombre del archivo ejecutable donde reside la nueva imagen del proceso.
file: se utiliza para construr el nombre del archivo ejecutable. Si el argumento file contiene el carcter /,
entonces el argumento file constituye el nombre del archivo ejecutable. Casa contrario, el prefijo del nombre para el
archivo se construye por medio de la bsqueda en los directorios pasados en la variable de entrono PATH.
argv contiene los argumentos pasadas al programa y debera acabar con un puntero NULL.
envp apunta al entorno que se pasar al nuevo proceso y se obtiene de la variable externa environ.
Los descriptores de los archivos abiertos previamente por le proceso que realiza la llamada exec permanecen
abiertos en la nueva imagen del proceso, excepto aquellos abiertos con el valor FD_CLOEXEC.
Las seales con la accin por defecto seguirn por defecto. Las seales ignoradas seguirn ignoradas por el nuevo
proceso y las seales con manejadores activados tomaran la acciones por defecto en la nueva imagen del proceso.
Atributos que se mantienen despus de la llamada:

PID

PPID

UID

GID

EUID

EGID

Directorio de trabajo actual (Work Directory)

Mscara de creacin de archivos.

Mscara de seales del proceso.

Seales pendientes.

// Ejemplo: Programa que ejecuta el comando ls l


#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
int status;
pid = fork();
switch(pid)
{
case -1: /* error del fork() */
exit(-1);
case 0: /* proceso hijo */
execlp("ls","ls","-l",NULL);
perror("exec");
break;
default: /* padre */
printf("Proceso padre\n");
9 DE 48 CTEDRA SISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
while(pid != wait(&status));
}
}

// Ejemplo: Programa que ejecuta el comando ls l mediante execvp


#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
pid_t pid;
char *argumentos[3];
argumentos[0] = "ls";
argumentos[1] = "-l";
argumentos[2] = NULL;
pid = fork();
switch(pid)
{
case -1: /* error del fork() */
exit(-1);
case 0: /* proceso hijo */
execvp(argumentos[0], argumentos);
perror("exec");
break;
default: /* padre */
printf("Proceso padre\n");
}
}

// Ejemplo: Programa que ejecuta el comando desde el shell


#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
pid_t pid;
pid = fork();
switch(pid)
{
case -1: /* error del fork() */
perror("fork");
break;
case 0: /* proceso hijo */
10 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
if (execvp(argv[1], &argv[1])< 0)
perror("exec");
break;
default: /* padre */
printf("Proceso padre\n");
}
}

2- SERVICIOS POSIX PARA LA GESTIN DE HILOS (THREAD): (CARRETERO PEREZ )


2.1- Atributos de un thread:
Cada hilo en POSIX tiene asociado una serie de atributos que representa sus propiedades. Los valores de estos se
almacenan en un objeto atributo de tipo pthread_attr_t.
a) Crear un atributo:
Permite iniciar una estructura atributo que se puede utilizar para crea nuevos procesos ligeros.
int pthread_attr_init(pthread_attr_t *attr);

b) Destruir atributos:
int pthread_attr_destroy(pthread_attr_t *attr);

c) Asignar el tamao de la pila:


Cada hilo tiene una pila cuyo tamao se pude establecer mediante esta funcin.
int pthread_attr_setstacksize(pthread_attr_t *attr, int stacksize);

d) Determinar el tamao de la pila:


int pthread_attr_getstacksize(pthread_attr_t *attr, int *stacksize)

e) Establecer el estado de terminacin:


int phtread_attr_setdatachstate(pthread_attr_t *attr, int detachstate;
Si el valor del argumento detachstate es PTHREAD_CREATE_DETACHED, el proceso ligero que se cree con esos
atributos se considerar como independiente y liberar sus recursos cuando finalice su ejecucin. Si el valor del
argumento detachstate es PTHREAD_CREATE_JOINABLE, el proceso ligero se crea como no independiente y no
liberar sus recursos cuando finalice su ejecucin. En este caso es necesario que otro proceso ligero espere
por su finalizacin. Esta espera se consigue mediante el servicio pthread_join.

11 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
2.2- Creacin e identificacin de procesos ligeros:
a) Crear un proceso ligero:
int pthread_create(pthread_t *thread, pthread_attr_r *attr, void *(*start routine) (void *), void *arg);
El primer argumento de la funcin apunta al identificador del proceso ligero que se crea, este identificador
viene determinado por el tipo pthread_t. El segundo argumento especifica los atributos de ejecucin asociados
al nuevo proceso ligero. Si el valor de este segundo argumento es NULL, se utilizarn los atributos por defecto,
que incluyen la creacin del proceso como no independiente. El tercer argumento indica el nombre de la
funcin a ejecutar cuando el proceso ligero comienza su ejecucin. Esta funcin requiere un solo parmetro
que se especifica con el cuarto argumento, arg.
b) Obtener el identificador de un proceso ligero:
pthread_t pthread_self()

2.3- Terminacin de procesos ligeros:


a) Esperar la terminacin de un proceso ligero:
Este servicio es similar a wait, pero a diferencia de ste, es necesario especificar el proceso ligero por el que se
quiere esperar, que no tiene por qu ser un proceso ligero hijo.
int pthread_join(pthread thid, void **value);
La funcin suspende la ejecucin del proceso ligero que la invoca hasta que el proceso ligero con identificador
thid finalice su ejecucin. La funcin devuelve en el segundo argumento el valor que pasa el proceso ligero que
finaliza su ejecucin en el servicio pthread_exit, que se ver a continuacin. nicamente se pude solicitar el
servicio pthread_join sobre procesos ligeros creados como no independientes.
b) Finalizar la ejecucin de un proceso ligero:
int pthread_exit(void *value)
Incluye un puntero a una estructura que es devuelta al proceso ligero que ha ejecutado la correspondiente
llamada a pthread_join, lo que es mucho ms genrico que el parmetro que permite el servicio wait.

12 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II

En la figura se muestra una jerarqua de procesos ligeros. Se supone que el proceso ligero A es el primario, por lo
que corresponde a la ejecucin del main. Los proceso B, C, y D se han creado mediante pthread_create() y ejecutan
respectivamente los procedimientos b(), c() y d(). El proceso ligero D se ha creado como no independiente por lo
que otro proceso puede hacer una operacin join sobre l. La figura muestra que le proceso ligero C hace una
operacin join sobre D, por lo que queda bloqueado hasta que termine.

//Ejemplo
//Programa que crea dos procesos ligeros no independientes
#include <pthread.h>
#include <stdio.h>
void *func(void * jj){
printf("Thread %d \n", pthread_self());
pthread_exit(0);
}
int main()
{
pthread_t th1, th2;
/* se crean dos procesos ligeros con atributos por defecto */
pthread_create(&th1, NULL, func, NULL);
pthread_create(&th2, NULL, func, NULL);
printf("El proceso ligero principal continua ejecutando\n");
/* se espera su terminacin */
pthread_join(th1, NULL);
pthread_join(th2, NULL);

13 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
exit(0);
}
/* Ejemplo
Programa que crea diez procesos ligeros independientes, que liberen sus recursos cuando finalizan ( se han creado con
el atributo PTHREAD_CREATE_DETACHED). En este caso no se puede esperar la terminacin de los procesos ligeros,
por lo que el proceso ligero principal que ejecuta el cdigo de la funcin main debe continuar su ejecucin en paralelo
con ellos. Para evitar que el proceso ligero principal finalice la ejecucin de la funcin main, lo que supone la ejecucin
del servicio exit y, por lo tanto, la finalizacin de todo el proceso, junto con todos los procesos ligeros, el proceso ligero
principal suspende su ejecucin durante cinco segundo para dar tiempo a la creacin y destruccin delos procesos
ligeros que se han creado.
La ejecucin de exit supone la finalizacin del proceso que ejecuta la llamada. Esto supone, por lo tanto, la finalizacin
de todos sus procesos ligeros, ya que stos slo tienen sentido dentro del contexto de un proceso. */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#define MAX_THREADS 10
void *func(void *jj){
printf("Thread %d \n", pthread_self());
pthread_exit(0);
}
int main(void)
{
int j;
pthread_attr_t attr;
pthread_t thid[MAX_THREADS];
/* Se inicial los atributos y se marcan como independientes */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
for(j = 0; j < MAX_THREADS; j ++)
pthread_create(&thid[j], &attr, func, NULL);
/* El proceso ligero principal no puede esperar la finalizacin */
/* de los procesos ligeros que creado y se suspende durante un */
/* cierto tiempo esperando su finalizacin */
sleep(5);
}
//Ejemplo
//Programa que crea un proceso ligero por cada nmero introducido
#include <pthread.h>
#include <stdio.h>
#define MAX_THREADS 10
struct pal{
14 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
int n;
};
void *imprimir(void *n){
struct pal *j = (struct pal *) n;
printf("Thread %d %d \n", pthread_self(), j->n);
pthread_exit(0);
}
int main(void)
{
pthread_attr_t attr;
pthread_t thid;
int num;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
while(1){
printf("Escribir numero entero :\n");
scanf("%d", &num); /* espera */
pthread_create(&thid, &attr, &imprimir, &num);
}
}

15 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
COMUNICACIN ENTRE PROCESOS EN LINUX

1- INTRODUCCIN
Los medios IPC (Inter-Process Communication) de Linux proporcionan un mtodo para que mltiples procesos se
comuniquen unos con otros. Hay varios mtodos de IPC disponibles para los programadores Linux en C:

Pipes UNIX Half-duplex

FIFOs (pipes con nombre)

Colas de mensajes estilo SYSV

Semforos estilo SYSV

Segmentos de memoria compartida estilo SYSV

Sockets (estilo Berkeley)

Seales
Los tubos, mensajes y memoria compartida proporcionan un medio de comunicacin de datos entre procesos,
mientras que los semforos y las seales se usan para provocar acciones en otros procesos.
Estos medios, cuando se usan de forma efectiva, proporciona una base slida para el desarrollo de cliente/servidor
en cualquier sistema UNIX (incluido Linux).

2- IPC EN S ISTEMA V
2.1 Conceptos fundamentales:
Con Unix Sistema V, AT&T introdujo tres nuevas formas de las facilidades IPC (colas de mensajes, semforos y
memoria compartida). Mientras que el comit POSIX aun no ha completado su estandarizacin de estas facilidades, la
mayora de las implementaciones soportan stas. Adems, Berkeley (BSD) usa sockets como su forma primaria de IPC,
ms que los elementos del Sistema V. Linux tiene la habilidad de usar ambas formas de IPC (BSD y System V).
Identificadores IPC
Cada objeto IPC tiene un nico identificador IPC asociado con l. Cuando decimos objeto IPC, hablamos de una
simple cola de mensaje, semforo o segmento de memoria compartida. Se usa este identificador, dentro del ncleo,
para identificar de forma nica un objeto IPC. Por ejemplo, para acceder un segmento particular memoria compartida,
lo nico que requiere es el valor del ID que se le ha asignado a ese segmento.
La unicidad de un identificador es importante segn el tipo de objeto en cuestin. Para ilustrar esto, supondremos
un identificador numrico 12345". No puede haber nunca dos colas de mensajes con este mismo identificador, pero
existe la posibilidad que existan una cola de mensajes y un segmento de memoria compartida que poseen el mismo
identificador numrico.
Claves IPC
Para obtener un identificador nico, debe utilizarse una clave. Esta debe ser conocida por ambos procesos cliente y
servidor. Este es el primer paso para construir el entorno cliente/servidor de una aplicacin.
Cuando usted llama por telfono a alguien, debe conocer su nmero. Adems, la compaa telefnica debe conocer
cmo dirigir su llamada al destino. Una vez que el receptor responde a su llamada, la conexin tiene lugar.
En el caso de los mecanismos IPC de Sistema V, el telfono" coincide con el tipo de objeto usado (semforo, cola
de mensaje, etc). El nmero de telfono, se puede comparar con la clave IPC.
La clave puede ser el mismo valor cada vez cada vez que se ejecuta el programa, incluyendo su valor en cdigo.
Esta es una desventaja pues la clave requerida puede estar ya en uso. Por eso, la funcin ftok() nos ser til para
generar claves no utilizadas para el cliente y el servidor.

FUNCIN DE LIBRERA: ftok();


PROTOTIPO: key_t ftok ( char *nombre, char proj );
16 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006
RETORNA: nueva clave IPC si tuvo xito. -1 si no tuvo xito, dejando errno con el valor de la llamada stat()

SISTEMAS OPERATIVOS II

La clave devuelta por ftok() se genera por la combinacin del nmero del i-nodo y el nmero menor de dispositivo
del archivo argumento, con el carcter identificador del segundo argumento. Este no garantiza la unicidad, pero una
aplicacin puede comprobar las colisiones y reintentar la generacin de la clave.
key_t miclave;
miclave = ftok("/tmp/miaplic", 'a');
En el caso anterior el directorio /tmp/miaplic se combina con la letra 'a'. Otro ejemplo comn es usar el directorio
actual:
key_t miclave;
mykey = ftok(".", 'a');
El algoritmo de la generacin de la clave usado est completamente a la discrecin del programador de la
aplicacin. Mientras que tome medidas para prevenir las condiciones crticas, bloqueos, etc, cualquier mtodo es viable.
Para nuestros propsitos de demostracin, usaremos ftok().
El valor clave que se obtiene, se usa en las llamada al sistema IPC para crear u obtener acceso a los objetos IPC.
El comando ipcs
ipcs puede utilizarse para obtener el estado de todos los objetos IPC Sistema V.
ipcs
ipcs
ipcs
ipcs

-q: Mostrar solo colas de mensajes


-s: Mostrar solo los semforos
-m: Mostrar solo la memoria compartida
--help: Otros argumentos

Por defecto, se muestran las tres categoras. Considrese el siguiente ejemplo de salida del comando ipcs:
------ Shared Memory Segments -------shmid owner perms bytes nattch status
------ Semaphore Arrays -------semid owner perms nsems status
------ Message Queues -------msqid owner perms used-bytes messages
0 root 660 5 1
Aqu vemos una simple cola mensaje que tiene un identificador 0. Es propiedad del root, y tiene permisos 660, o
-rw-rw--. Hay un mensaje en la cola, y ese mensaje tiene un tamao total de 5 bytes. Los comandos ipcs son una
herramienta muy potente que proporciona una introduccin a los mecanismos de almacenamiento del ncleo para
objetos IPC.
El comando ipcrm
Se puede usar el comando ipcrm para quitar un objeto IPC del ncleo.
Mientras que los objetos IPC se pueden quitar mediante llamadas al sistema en el cdigo del usuario, aparece a
menudo la necesidad, sobre todo en ambientes de desarrollo, de quitar objetos IPC a mano. Su uso es simple:

17 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
ipcrm <msg | sem | shm> <IPC ID>
Simplemente especifique si el objeto a eliminar es una cola de mensaje (msg), un semforo (sem), o un segmento
de memoria compartida (shm).
El identificador de IPC se puede obtener mediante los comandos ipcs. Tiene que especificar el tipo de objeto, dado
que los identificadores son nicos dentro de un mismo tipo, pero no entre distintos tipos de objetos.

2.2 Semforos:
Conceptos Bsicos
Los semforos se pueden describir mejor como contadores que se usan para controlar el acceso a recursos
compartidos por mltiples procesos. Se usan con ms frecuencia como un mecanismo de cierre para prevenir que los
procesos accedan a un recurso particular mientras otro proceso lo est utilizando. Los semforos son a menudo
considerados como el ms difcil asir de los tres tipos de objetos Sistema V IPC. Para comprender totalmente los
semforos, los discutiremos brevemente antes de comenzar cualquier llamada al sistema y teora operacional.
El nombre de semforo es realmente un trmino viejo del ferrocarril, que se usaba para prevenir accidentes, en el
cruce de las vas de los viejos carros.
Exactamente lo mismo se puede decir sobre un semforo. Si el semforo est abierto (los brazos en alto), entonces
un recurso est disponible (los carros cruzaran las vas). Sin embargo, si el semforo est cerrado (los brazos estn
abajo), entonces el recurso no estn disponible (los carros deben esperar).
Mientras que con este ejemplo simple nos introduce el concepto, es importante darse cuenta de que los semforos
en POSIX se llevan a cabo realmente como conjuntos, en lugar de como entidades solas. Por supuesto, un conjunto de
semforos dado puede tener slo un semforo, como en nuestro ejemplo del ferrocarril.
Quizs otra aproximacin al concepto de semforos, sera pensar en ellos como contadores de recursos.
Apliquemos este concepto a otro caso del mundo real. Considere un spooler de impresin, capaz de manipular
impresoras mltiples, con cada manejo de la impresora con demandas de la impresin mltiples. Un hipottico
manejador del spool de impresin utilizar un conjunto de semforos para supervisar el acceso a cada impresora.
Suponemos que en nuestro cuarto de impresoras, tenemos 5 impresoras conectadas. Nuestro manejador del spool
asigna un conjunto de 5 semforos a l, uno por cada impresora del sistema. Como cada impresora es capaz de
imprimir fsicamente un nico trabajo en un instante, cada uno de nuestros cinco semforos se inicializar con un valor
de 1 (uno), lo que significa que estn todas en lnea, y aceptan trabajos.
Juan enva una peticin de impresin al spooler. El manejador de la impresin mira los semforos, y encuentra que
el primer semforo tiene un valor de uno. Ante enviar la peticin de Juan al aparato fsico, el manejador de impresin
decrementa el semforo de la impresora correspondiente. Ahora, el valor de ese semforo es cero. En nuestro
ejemplo no se pueden enviar a esa impresora ninguna otra peticin hasta que sea distinto de cero.
Cuando el trabajo de Juan se ha realizado, el gestor de impresin incrementa el valor del semforo
correspondiente. Su valor vuelve a ser uno (1), lo que indica que el recurso vuelve a estar disponible. Naturalmente, si
los cinco semforos tienen valor cero, indica que todas las impresoras estn ocupadas con peticiones y no se pueden
atender ms.
Aunque este es un ejemplo simple, procure no confundirse con el valor inicial (1) dado a los semforos. En
realidad, cuando se ven como contadores de recursos, pueden ser iniciados con cualquier valor positivo, y no estn
limitados a valer 0 o 1. Si las impresoras de nuestro ejemplo fuesen capaces de aceptar 10 trabajos de impresin,
habramos iniciado sus semforos con el valor 10, decrementndolo en 1 cada vez que lega un trabajo nuevo y
reincrementndolo al terminar otro. Como descubriremos en este captulo, el funcionamiento de los semforos tiene
mucha relacin con el sistema de memoria compartida, actuando como guardianes para evitar mltiples escrituras en la
misma zona de memoria.

18 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Antes de entrar en las llamadas al sistema relacionadas, repasemos varias estructuras de datos internas usadas en
las operaciones con semforos.
Estructuras de datos internas
Veamos brevemente las estructuras de datos mantenidas por el ncleo para los conjuntos de semforos.
El ncleo mantiene unas estructuras de datos internas especiales por cada conjunto de semforos dentro de su
espacio de direcciones. Esta estructura es de tipo semid_ds y se define en linux/sem.h como sigue:
/* Hay una estructura semid_ds por cada juego de semforos */
struct semid_ds {
struct ipc_perm sem_perm; /* permisos .. ver ipc.h */
time_t sem_otime; /* ultimo instante semop */
time_t sem_ctime; /* ultimo instante de cambio */
struct sem *sem_base; /* puntero al primer semforo del array */
struct wait_queue *eventn;
struct wait_queue *eventz;
struct sem_undo *undo; /* deshacer peticiones del array*/
ushort sem_nsems; /* no. de semaforos del array */
};
Como con las colas de mensaje, las operaciones con esta estructura son ejecutados por llamadas especiales al
sistema especial, y no se deben usar directamente. Aqu tenemos las descripciones de los campos ms interesantes:
sem_perm
Este es un caso de la estructura ipc perm, que se define en linux/ipc.h. Toma la informacin de los permisos
para el conjunto de semforos, incluyendo permisos de acceso e informacin sobre el creador del conjunto
(uid, etc).
sem_otime
Instante de la ltima operacin semop().
sem_ctime
Instante del ltimo cambio de modo.
sem_base
Puntero al primer semforo del array (ver siguiente estructura).
sem_undo
Nmero de solicitudes de deshacer en el array.
sem_nsems
Nmero de semforos en el conjunto (el array)
Estructura sem del ncleo
En la estructura semid_ds, hay un puntero a la base del array del semforo. Cada miembro del array es del tipo
estructura sem. Tambin se define en linux/sem.h:
/* Una estructura por cada juego de semforos */
struct sem {
19 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
short sempid; /* pid de ultima operacin */
ushort semval; /* valor actual */
ushort semncnt; /* num. procesos esperando para incrementarlo */
ushort semzcnt; /* num. procesos esperando que semval sea 0 */
};
sempid
El PID (identificador del proceso) que realiz la ltima operacin.
semval
Valor actual del semforo.
semncnt
Nmero de procesos esperando la disponibilidad del recurso.
semzcnt
cantidad de semforos esperando que semval = 0

LLAMADA AL SISTEMA: semget()


Se usa para crear un nuevo conjunto o acceder a uno existente.
LLAMADA AL SISTEMA: semget();
PROTOTIPO: int semget ( key_t key, int nsems, int semflg );
RETORNA: Identificador IPC del conjunto, si tuvo xito.
-1 si existi un error y errno=
EACCESS (permiso denegado)
EEXIST (no puede crearse pues existe (IPC_EXCL))
EIDRM (conjunto marcado para borrarse)
ENOENT (no existe el conjunto ni se indic IPC_CREAT)
ENOMEM (No hay memoria suficiente para crear)
ENOSPC (Limite de conjuntos excedido)

El primer argumento de semget() es el valor clave (en nuestro caso devuelto por la llamada a ftok()). Este valor
clave se compara con los valores clave existentes en el ncleo para otros conjuntos de semforos. Ahora, las
operaciones de apertura o acceso depende del contenido del argumento semflg.
Desafortunadamente, otro proceso podra haber elegido la misma clave, por lo que ambos accedera al mismo
semforo. Usando la constante especial IPC_PRIVATE como valor de la clave se busca garantizar que un nuevo
semforo sea crado.
Un nuevo conjunto de nsems semforos se crea si key tiene el valor IPC_PRIVATE, o si key no vale IPC_PRIVATE,
no hay un conjunto de semforos asociado a key, y el bit IPC_CREAT vale 1 en semflg
IPC_CREAT
Crea el juego de semforos si no existe ya en el ncleo.
IPC_EXCL
Al usarlo con IPC CREAT, falla si el conjunto de semforos existe ya. Si se usa IPC_CREAT solo, semget(), bien
devuelve el identificador del semforo para un conjunto nuevo creado, o devuelve el identificador para un
20 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
conjunto que existe con el mismo valor clave. Si se usa IPC_EXCL junto con IPC_CREAT, entonces se crea un
conjunto nuevo, o si el conjunto existe, la llamada falla con 1. IPC_EXCL es intil por s mismo, pero cuando
se combina con IPC_CREAT, se puede usar como una facilidad garantizar que ningn semforo existente se
abra accidentalmente para accederlo.
Como sucede en otros puntos del IPC del Sistema V, puede aplicarse a los parmetros anteriores, un nmero
octal para dar la mscara de permisos de acceso de los semforos. Debe hacerse con una operacin OR
binaria. El argumento nsems especifica el nmero de semforos que se deben crear en un conjunto nuevo.
Este representa el nmero de impresores en nuestro cuarto de impresin ficticio descrito antes. El mximo
nmero de semforos en un conjunto se define en\linux/sem.h" como:
#define SEMMSL 32 /* <=512 max num de semforos por id */
Observe que el argumento nsems se ignora si abre explcitamente un conjunto existente.
Creemos ahora una funcin de cobertura para abrir o cerrar juegos de semforos:
int abrir_conj_semaforos( key_t clave, int numsems ){
int sid;
if ( numsems > 0)
return semget(clave, numsems, IPC_CREAT | 0660 );
else
return(-1);
}
Vea que se usan explcitamente los permisos 0660. Esta pequea funcin retornar, bien un identificador entero
del conjunto de semforos, o bien un -1 si hubo un error.
En el ejemplo del final de esta seccin, observe la utilizacin del flag IPC_EXCL para determinar si el conjunto de
semforos existe ya o no.

LLAMADA AL SISTEMA: semop()


LLAMADA AL SISTEMA: semop();
PROTOTIPO: int semop ( int semid, struct sembuf *sops, unsigned nsops);
RETURNS: 0 si tuvo xito (todas las operaciones realizadas)
-1 si existi un error y la variable errno =
E2BIG (nsops mayor que mx. nmero de opers. permitidas atmicamente)
EACCESS (permiso denegado)
EAGA IN (IPC_NOWAIT incluido, la operacin no termin)
EFAULT (direccin no v_alida en el parmetro sops)
EIDRM (el conj. de semforos fue borrado)
EINTR (Recibida seal durante la espera)
EINVAL (el conj. no existe, o semid invlido)
ENOMEM (SEM_UNDO incluido, sin memoria suficiente crear la estructura de retroceso
necesaria)
ERANGE (valor del semforo fuera de rango)

El primer argumento de semop() es el identificador IPC (en nuestro caso devuelto por una llamada a semget(). El
segundo argumento (sops) es un puntero a un array de operaciones para que se ejecuta en el conjunto de semforo,
mientras el tercer argumento (nsops) es el nmero de operaciones en ese array.
21 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
El argumento sops apunta a un array del tipo sembuf. Se declara esta estructura en linux/sem.h como sigue:
/* La llamada al sistema semop usa un array de este tipo */
struct sembuf {
ushort sem_num;
/* posicin en el array */
short sem_op;
/* operacin del semforo */
short sem_flg;
/* flags de la operacin */
};
sem_num
Nmero de semforo sobre el que desea actuar, recuerde que en Linux no se crean semforos individuales,
sino conjuntos de semforos. Este atributo permite elegir o seleccionar el semforo del conjunto sobre el que se desea
actual
sem_op
Operacin a realizar (positiva, negativa o cero)
sem_flg
Flags (parmetros) de la operacin
Si sem_op es negativo, entonces su valor se resta del valor del semforo. Este pone en correlacin con la obtencin
de recursos que controla el semforo o los monitores de acceso. Si no se especifica IPC_NOWAIT, entonces proceso
que efecta la llamada duerme hasta que los recursos solicitados estn disponible en el semforo, es decir, que si al
Decrementar el semforo este queda con un valor negativo el proceso se bloquea.
Si sem_op es positivo, entonces su valor se aade (se suma) al semforo. Este se pone en correlacin con los
recursos devueltos al conjunto de semforos de la aplicacin. Siempre se deben devolver los recursos al conjunto de
semforos cuando ya no se necesiten ms.
Finalmente, si sem_op vale cero (0), entonces el proceso que efecta la llamada dormira hasta que el valor del
semforo sea 0.
Para explicar la llamada de semop, volvamos a ver nuestro ejemplo de impresin. Supongamos una nica una
impresora, capaz de nico un trabajo en un instante. Creamos un conjunto de semforos con nico semforo en l
(slo una impresora), e inicializa ese semforo con un valor de uno (nico un trabajo en un instante).
Cada vez que deseemos enviarle un trabajo a esta impresora, primeros necesitamos asegura que el recurso est
disponible. Hacemos este para intentar obtener una unidad del semforo. Cargamos un array sembuf para realizar la
operacin:

struct sembuf sem_lock = { 0, -1, IPC_NOWAIT };

La traduccin de la inicializacin de la anterior estructura indica que se decrementar en una unidad el semforo 0
del conjunto de semforos.
En otras palabras, se obtendra una unidad de recursos del nico semforo de nuestro conjunto (miembro 0). Se
especifica IPC_NOWAIT, as la llamada o se produce inmediatamente, o falla si otro trabajo de impresin est activo en
ese momento. Aqu hay un ejemplo de como usar esta inicializacin de la estructura sembuf con la llamada al sistema
semop:
if((semop(sid, &sem_lock, 1) == -1)
perror("semop");
22 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
El tercer argumento (nsops) dice que estamos slo ejecutando una (1) operacin (hay slo una estructura sembuf
en nuestra array de operaciones).
El argumento sid es el identificador IPC para nuestro conjunto de semforos.
Cuando nuestro trabajo de impresin ha terminado, debemos devolver los recursos al conjunto de semforos, de
manera que otros puedan usar la impresora.
Esto es similar a hacer un wait() en la teora de los semforos, con la nica diferencia es que se esta especificando
como IPC_NOWAIT, lo que significa que la funcin a decrementar el semforo y encontrarse con un valor negativo no
bloquea el proceso, simplemente falla y deja que contine su ejecucin. Para que esta llamada al sistema sea
equivalente a la operacin wait() en teora de semforos, no se debe indicar IPC_NOWAIT.
struct sembuf sem_unlock = { 0, 1, IPC_NOWAIT };
La traduccin de la estructura anteriormente inicializada indica que un valor de 1 se agrega a semforo nmero 0
en el conjunto de semforos. En otras palabras, una unidad de recursos se devolver al conjunto. Esto es equivalente
a hacer un signal() en la teora de los semforos
LLAMADA AL SISTEMA: semctl()

LLAMADA AL SISTEMA: semctl();


PROTOTIPO: int semctl ( int semid, int semnum, int cmd, union semun arg );
RETURNS: entero positivo si _exito
-1 si error: errno = EACCESS (permiso denegado)
EFAULT (direccin invlida en el argumento arg)
EIDRM (el juego de semforos fue borrado)
EINVAL (el conj. no existe, o semid no es vlido)
EPERM (El EUID no tiene privilegios para el comando incluido en arg)
ERANGE (Valor para semforo fuera de rango)
NOTAS: Realiza operaciones de control sobre conjuntos de semforos
La llamada al sistema semctl se usa para desempear operaciones de control sobre un conjunto de semforo. Esta
llamada es anloga a la llamada al sistema msgctl que se usa para operaciones sobre las colas de mensaje. Si usted
compara las listas de argumento de las dos llamadas al sistema, notar que la lista para semctl vara ligeramente con la
de msgctl.
Las llamados al sistema utilizan un argumento cmd, para la especificacin del comando a ser realizado sobre el
objeto IPC. La diferencia con las colas de mensajes es que con los semforos, se soportan los comandos operacionales
adicionales, as requieren unos tipos de estructuras de datos ms complejos en el argumento final. El uso del tipo unin
confunde a muchos programadores de forma considerable. Nosotros estudiaremos esta estructura cuidadosamente, en
un esfuerzo para impedir cualquier confusin.
El argumento cmd representa el comando a ejecutar con el conjunto. Como puede ver, incluye los conocidos
comandos IPC_STAT/IPC_SET, junto a otros especficos de conjuntos de semforos:
IPC_STAT
Obtiene la estructura semid ds de un conjunto y la guarda en la direccin del argumento buf en la unin
semun.

23 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
IPC_SET
Establece el valor del miembro ipc perm de la estructura semid ds de un conjunto. Obtiene los valores del
argumento buf de la unin semun.
IPC_RMID
Elimina el conjunto de semforos.
GETALL
Se usa para obtener los valores de todos los semforos del conjunto.
Los valores enteros se almacenan en un array de enteros cortos sin signo, apuntado por el miembro array de la
unin.
GETNCNT
Devuelve el nmero de procesos que esperan recursos.
GETPID
Retorna el PID del proceso que realiz la ltima llamada semop.
GETVAL
Devuelve el valor de uno de los semforos del conjunto.
GETZCNT
Devuelve el nmero de procesos que esperan la disponibilidad del 100% de recurso.
SETALL
Coloca todos los valores de semforos con una serie de valores contenidos en el miembro array de la unin.
SETVAL
Coloca el valor de un semforo individual con el miembro val de la unin.
El argumento arg representa un ejemplo de tipo semun. Esta unin particular se declara en linux/sem.h como se
indica a continuacin:
/* argumento para llamadas a semctl */
union semun {
int val; /* valor para SETVAL */
struct semid_ds *buf; /* buffer para IPC_STAT e IPC_SET */
ushort *array; /* array para GETALL y SETALL */
struct seminfo *__buf; /* buffer para IPC_INFO */
void *__pad;
};
val
Se usa con el comando SETVAL, para indicar el valor a poner en el semforo.
buf
Se usa con los comandos IPC_STAT/IPC_SET. Es como una copia de la estructura de datos interna que tiene el
ncleo para los semforos.
array
Puntero que se usa en los comandos GETALL/SETALL. Debe apuntar a una matriz de nmeros enteros donde se
ponen o recuperan valores de los semforos.
24 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Los dems argumentos, buf y pad, se usan internamente en el ncleo y no son de excesiva utilidad para el
programador. Adems son especficos para el sistema operativo Linux y no se encuentran en otras versiones de
UNIX.
Ya que esta llamada al sistema es de las ms complicadas que hemos visto, pondremos diversos ejemplos para
su uso. La siguiente funcin devuelve el valor del semforo indicado. El ltimo argumento de la llamada (la
unin), es ignorada con el comando GETVAL por lo que no la incluimos:
int obtener_sem_val( int sid, int semnum ){
return( semctl(sid, semnum, GETVAL, 0));
}

Considrese la siguiente funcin, que se debe usar para iniciar un nuevo semforo:
void iniciar_semaforo( int sid, int semnum, int initval){
union semun semopts;
semopts.val = initval;
semctl( sid, semnum, SETVAL, semopts);
}
Observe que el argumento final de semctl es una copia de la unin, ms que un puntero a l. Mientras nosotros
estamos en el tema de la unin como argumento, me permito demostrar una equivocacin ms bien comn cuando usa
este llamado de sistema.
Recordamos del proyecto msgtool que los comandos IPC_STAT e IPC_SET se usaron para alterar los permisos sobre la
cola. Mientras estos comandos se soportan, en la implementacin de un semforo implementacin, su uso es un poco
diferente, como las estructuras de datos internas e recuperan y copian desde un miembro de la unin, ms bien que
una entidad simple. Puede encontrar el error en este cdigo?
/* Los permisos se pasan como texto (ejemplo: "660") */
void changemode(int sid, char *mode){
int rc;
struct semid_ds mysemds;
/* Obtener valores actuales */
if((rc = semctl(sid, 0, IPC_STAT, semopts)) == -1){
perror("semctl");
exit(1);
}
printf("Antiguos permisos: %o\n", semopts.buf->sem_perm.mode);
/* Cambiar los permisos del semaforo */
sscanf(mode, "%o", &semopts.buf->sem_perm.mode);
/* Actualizar estructura de datos interna */
semctl(sid, 0, IPC_SET, semopts);
printf("Actualizado...\n");
}
El cdigo intenta de hacer una copia local de las estructuras de datos internas estructura para el conjunto, modifica los
permisos, e IPC_SET los devuelve al ncleo. Sin embargo, la primera llamada a semctl devuelve EFAULT, o direccin
errnea para el ltimo argumento (la unin!). Adems, si no hubiramos verificado los errores de la llamada, nosotros
habramos conseguido un fallo de memoria. Por qu?
25 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Recuerde que los comandos IPC_SET/IPC_STAT usan el miembro buf de la unin, que es un puntero al tipo semid_ds.
Los punteros, son punteros, son punteros y son punteros! El miembro buf debe indicar alguna ubicacin vlida de
almacenamiento para que nuestra funcin trabaje adecuadamente.
Considere esta versin:
void cambiamodo(int sid, char *mode){
int rc;
struct semid_ds mysemds;
/* Obtener valores actuales de estructura interna */
/* !Antes de nada apuntar a nuestra copia local! */
semopts.buf = &mysemds;
/* !Intentemos esto de nuevo! */
if((rc = semctl(sid, 0, IPC_STAT, semopts)) == -1){
perror("semctl");
exit(1);
}
printf("Antiguos permisos: %o\n", semopts.buf->sem_perm.mode);
/* Cambiar permisos */
sscanf(mode, "%o", &semopts.buf->sem_perm.mode);
/* Actualizar estructura interna */
semctl(sid, 0, IPC_SET, semopts);
printf("Actualizado...\n");
}

3- Memoria Compartida
Conceptos bsicos
La memoria compartida se puede describir mejor como el mapeo (mapping) de un rea (segmento) de memoria
que se combinara y compartir por ms de un de proceso. Esta es por mucho la forma ms rpida de IPC, porque no
hay intermediacin (es decir, un tubo, una cola de mensaje, etc). En su lugar, la informacin se combina directamente
en un segmento de memoria, y en el espacio de direcciones del proceso llamante. Un segmento puede ser creado por
un proceso, y consecutivamente escrito a y ledo por cualquier nmero de procesos.
Estructuras de datos internas y de usuario
Estructuras de datos que mantiene el ncleo para cada segmento de memoria compartida.
Estructura shmid_ds del ncleo Como con la cola de mensaje y los conjuntos de semforos, el ncleo mantiene
unas estructuras de datos internas especiales para cada segmento compartido de memoria que existe dentro de su
espacio de direcciones. Esta estructura es de tipo shmid_ds, y se define en linux/shm.h como se indica a continuacin:
/* Por cada segmento de memoria compartida, el ncleo mantiene una estructura como esta */
struct shmid_ds {
struct ipc_perm shm_perm;
/* permisos operacion */
int shm_segsz;
/* tamanyo segmento (bytes) */
time_t shm_atime;
/* instante ultimo enlace */
time_t shm_dtime;
/* instante ult. desenlace */
time_t shm_ctime;
/* instante ultimo cambio */
unsigned short shm_cpid;
/* pid del creador */
unsigned short shm_lpid;
/* pid del ultimo operador */
26 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
short shm_nattch;

/* num. de enlaces act. */


/* lo que sigue es privado */
unsigned short shm_npages; /* tam. segmento (paginas) */
unsigned long *shm_pages; /* array de ptr. a marcos -> SHMMAX struct vm_area_struct *attaches;
/* descriptor de enlaces */
};

Las operaciones sobre esta estructura son realizadas por una llamada especial al sistema, y no deberan ser
realizadas directamente. Aqu se describen de los campos ms importantes:
shm_perm
Este es un ejemplo de la estructura ipc_perm, que se define en linux/ipc.h. Esto tiene la informacin de
permisos para el segmento, incluyendo los permisos de acceso, e informacin sobre el creador del segmento
(uid, etc).
shm_segsz
Tamao del segmento (en bytes).
shm_atime
Instante del ltimo enlace al segmento por parte de algn proceso.
shm_dtime
Instante del ltimo desenlace del segmento por parte de algn proceso.
shm_ctime
Instante del ltimo cambio de esta estructura (cambio de modo, etc).
shm_cpid
PID del proceso creador.
shm_lpid
PID del ltimo proceso que actu sobre el segmento.
shm_nattch
Nmero de procesos actualmente enlazados con el segmento.
LLAMADA AL SISTEMA: shmget()
Para crear un nuevo segmento de memoria compartida, o acceder a una existente, tenemos la llamada al sistema
shmget().
LLAMADA AL SISTEMA: shmget();
PROTOTIPO: int shmget ( key_t key, int size, int shmflg );
RETORNA: si tuvo exto retorna el identificador (ID) de segmento de memoria compartida
-1 existi un error: errno = EINVAL (Tam. de segmento invalido)
EEXIST (El segmento existe, no puede crearse)
EIDRM (Segmento borrado o marcado para borrarse)
ENOENT (No existe el segmento)
EACCES (Permiso denegado)
ENOMEM (No hay memoria suficiente)

27 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Es parecido a las correspondientes para las colas de mensaje y conjuntos de semforos.
El argumento primero de shmget() es el valor clave (en nuestro caso vuelto por una llamada a ftok()). Este valor clave
se compara entonces con valores claves existentes dentro de el ncleo de otros segmentos compartidos de memoria.
En esta situacin, las operaciones de apertura o de acceso dependen de los contenidos del argumento shmflg.
IPC_CREAT
Crea un segmento si no existe ya en el ncleo.
IPC_EXCL
Al usarlo con IPC CREAT, falla si el segmento ya existe. Si se usa IPC_CREAT sin nada ms, shmget() retornar,
bien el identificador del segmento recin creado, o bien el de un segmento que exista ya con la misma clave
IPC. Si se aade el comando IPC_EXCL, en caso de existir un segmento con la misma clave, la llamada al
sistema fallar, y si no se crear. De nuevo, puede aadirse un modo de acceso en octal, mediante la
operacin OR.
Preparemos una funcin para crear o localizar segmentos de memoria compartida:
int abrir_segmento( key_t clave, int size ){
int shmid;
if((shmid = shmget( clave, size, IPC_CREAT | 0660 )) == -1){
return(-1);
}
return(shmid);
}
Observe el uso de los permisos explcitos 0660. Esta sencilla funcin retornar un entero con el identificador del
segmento, o -1 si existi un error.
Los argumentos son, el valor de la clave IPC y el tamao deseado para el segmento (en bytes).
Una vez que un proceso obtiene un identificador de segmento vlido, el siguiente paso es mapear (attach) el
segmento en su propio espacio de direcciones.
LLAMADA AL SISTEMA: shmat()
LLAMADA AL SISTEMA : shmat();
PROTOTIPO: int shmat ( int shmid, char *shmaddr, int shmflg);
RETORNA: direccin de acceso al segmento, o -1 si hubo error:
errno = EINVAL (Identificador o direccin invlidos) ENOMEM (No hay memoria suficiente para ligarse)
EACCES (Permiso denegado)

Si el argumento addr es nulo (0), el ncleo intenta encontrar una zona no mapeada. Es la forma recomendada de
hacerlo. Se puede incluir una direccin, pero es algo que solo suele usarse para facilitar el uso con hardware propietario
o resolver conflictos con otras aplicaciones. La constante SHM_RND puede pasarse con un OR lgico en el argumento
shmflg para forzar una direccin pasada para ser pgina (se redondea al tamao ms cercano de pgina).
Adems, si se hace OR con la constante SHM_RDONLY y con el argumento de banderas, entonces el segmento
compartido de memoria se mapea, pero marcado como slo lectura.
Esta llamada es quizs la ms simple de usar. Considere esta funcin de envoltura, que se pasa un identificador
IPC vlido para un segmento, y devuelve la direccin a la que el segmento est enlazado:
28 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
char *ligar_segmento( int shmid ){
return(shmat(shmid, 0, 0));
}
Una vez que un segmento ha sido adecuadamente adjuntado, y un proceso tiene un puntero al comienzo del
segmento, la lectura y la escritura en el segmento se realizan referenciando el puntero.
Tenga cuidado de no perder el valor del puntero original! Si esto sucede, no habr ninguna manera de acceder a
la base (comienzo) del segmento.
LLAMADA AL SISTEMA: shmctl()

LLAMADA AL SISTEMA: shmctl();


PROTOTYPE: int shmctl ( int shmqid, int cmd, struct shmid_ds *buf );
RETURNS: 0 si xito, -1 si error:
errno = EACCES (No hay permiso de lectura y cmd es IPC_STAT)
EFAULT (Se ha suministrado una direccin invlida para los comandos IPC_SET e IPC_STAT)
EIDRM (El segmento fue borrado durante esta operacin)
EINVAL (shmqid invlido)
EPERM (Se ha intentado, sin permiso de escritura, el comando IPC_SET o IPC_RMID)
Los que valores vlidos de comando son:
IPC_STAT
Obtiene la estructura shmid_ds de un segmento y la almacena en la direccin del argumento buf.
IPC_SET
Ajusta el valor del miembro ipc_perm de la estructura, tomando el valor del argumento buf.
IPC_RMID
Marca un segmento para borrarse. El comando IPC_RMID no quita realmente un segmento del ncleo. Ms
bien, marca el segmento para eliminacin. La eliminacin real del mismo ocurre cuando el ltimo proceso
actualmente adjunto al segmento termina su relacin con l. Por supuesto, si ningn proceso est actualmente
asociado al segmento, la eliminacin es inmediata.
Para separar adecuadamente un segmento compartido de memoria, un proceso invoca la llamada al sistema
shmdt.
LLAMADA AL SISTEMA: shmdt()
LLAMADA AL SISTEMA: shmdt();
PROTOTIPO: int shmdt ( char *shmaddr );
RETURNS: -1 si error: errno = EINVAL (Dir. de enlace invlida)

29 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Cuando un segmento compartido de memoria no se necesita ms por un proceso, se debe separar con una
llamado al sistema. Como mencionamos antes, esto no es lo mismo que eliminar un segmento desde el ncleo!
Despus de separar con xito, el miembro shm_nattch de la estructura shmid_ds se decrementa en uno. Cuando este
valor alcanza el cero (0), el ncleo quitara fsicamente el segmento.

30 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
LLAMADAS AL SISTEMA DE LINUX EN ORDEN ALFABTICO:
exit - como exit pero con menos acciones (m+c)
accept - aceptar conexiones en un socket (m+c!)
access - comprobar permisos de usuario en un fichero (m+c)
acct - no implementada aun (mc)
adjtimex - obtener/ajustar variables de tiempo internas (-c)
afs syscall - reservada para el sistema de ficheros Andrew (-)
alarm - envi de SIGALRM tras un tiempo especificado (m+c)
bdush - vuelca buffers modificados al disco (-c)
bind - nombrar un socket para comunicaciones (m!c)
break - no implementada aun (-)
brk - cambiar el tamao del segmento de datos (mc)
chdir - cambiar el directorio de trabajo (m+c)
chmod - cambiar permisos en un fichero (m+c)
chown - cambiar propietario de un fichero (m+c)
chroot - cambiar el directorio raz (mc)
clone - ver fork (m-)
close - cerrar un fichero (m+c)
connect - enlazar dos sockets (m!c)
creat - crear un fichero (m+c)
create module - reservar espacio para un modulo del ncleo (-)
delete module - descargar modulo del ncleo (-)
dup - crear un duplicado de un descriptor de fichero (m+c)
dup2 - duplicar un descriptor (m+c)
execl, execlp, execle, ... - vease execve (m+!c)
execve - ejecutar un fichero (m+c)
exit - terminar un programa (m+c)
fchdir - cambiar directorio de trabajo por referencia ()
fchmod - vease chmod (mc)
fchown - cambiar propietario de un fichero (mc)
fclose - cerrar un fichero por referencia (m+!c)
fcntl - control de ficheros/descriptores (m+c)
ock - cambiar bloqueo de fichero (m!c)
fork - crear proceso hijo (m+c)
fpathconf - obtener info. de fichero por referencia (m+!c)
fread - leer matriz de datos de un fichero (m+!c)
fstat - obtener estado del fichero (m+c)
fstatfs - obtener estado del sistema de ficheros por referencia (mc)
fsync - escribir bloques modificados del fichero a disco (mc)
ftime - obtener fecha del fichero, en segundos desde 1970 (m!c)
ftruncate - cambiar tamao del fichero (mc)
fwrite - escribir matriz de datos binarios a un fichero (m+!c)
get kernel syms - obtener tabla de smbolos del kernel o su tamao (-)
getdomainname - obtener nombre de dominio del sistema (m!c)
getdtablesize - obtener tamao de la tabla de descriptores de fich. (m!c)
getegid - obtener id. de grupo efectivo (m+c)
geteuid - obtener id. de usuario efectivo (m+c)
getgid - obtener id. de grupo real (m+c)
getgroups - obtener grupos adicionales (m+c)
gethostid - obtener identificador del huesped (m!c)
gethostname - obtener nombre del huesped (m!c)
31 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
getitimer - obtener valor de temporizador (mc)
getpagesize - obtener tamao de pagina (m-!c)
getpeername - obtener direccin remota de un socket (m!c)
getpgid - obtener id. del grupo de procesos padre (+c)
getpgrp - obtener id. del grupo padre del proceso (m+c)
getpid - obtener id. del proceso (pid) (m+c)
getppid - obtener id. del proceso padre (m+c)
getpriority - obtener prioridades de usuario/grupo/proceso (mc)
getrlimit - obtener limites de recursos (mc)
getrusage - obtener uso de recursos (m)
getsockname - obtener direccin de un socket (m!c)
getsockopt - obtener opciones ajustadas en un socket (m!c)
gettimeofday - obtener segundos pasados desde 1970 (mc)
getuid - obtener id. de usuario real (uid) (m+c)
gtty - no implementada aun ()
idle - hacer candidato a expulsin al disco a un proceso (mc)
init module - incluir un modulo cargable (-)
ioctl - manipulacin de un dispositivo de caracter (mc)
ioperm - ajusta algunos permisos de e/s (m-c)
iopl - ajusta permisos de e/s (m-c)
ipc - comunicacin entre procesos (-c)
kill - enviar una seal a un proceso (m+c)
killpg - enviar una seal a un grupo de procesos (mc!)
klog - ver syslog (-!)
link - crear un enlace bsico a un fichero (m+c)
listen - escuchar conexiones en un socket (m!c)
llseek - lseek para ficheros grandes (-)
lock - no implementada aun ()
lseek - cambia el puntero de un fichero abierto (m+c)
lstat - obtiene estado de un fichero (mc)
mkdir - crea un directorio(m+c)
mknod - crea un dispositivo (mc)
mmap - mapea un fichero en memoria (mc)
modify ldt - lee o escribe tabla de descriptores locales (-)
mount - montar un sistema de ficheros (mc)
mprotect - controla permisos de acceso a una zona de memoria (-)
mpx - no implementada aun ()
msgctl - control de mensajes ipc (m!c)
msgget - obtiene un id. de cola de mensajes (m!c)
msgrcv - recibe un mensaje ipc (m!c)
msgsnd - enva un mensaje ipc (m!c)
munmap - quita un fichero de memoria (mc)
nice - cambia prioridad del proceso (mc)
oldfstat - a extinguir
oldlstat - a extinguir
oldolduname - a extinguir
oldstat - a extinguir
olduname - a extinguir
open - abrir un fichero (m+c)
pathconf - obtener info. de un fichero (m+!c)
pause - dormir hasta la llegada de una seal (m+c)
personality - cambiar dominio de ejecucin en iBCS (-)
phys - no implementada aun (m)
32 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
pipe - crea una tubera (m+c)
prof - no implementada aun ()
profil - perfil de ejecucin (m!c)
ptrace - traza proceso hijo (mc)
quotactl - no implementada aun ()
read - lee datos de un fichero (m+c)
readv - lee bloques de un fichero (m!c)
readdir - lee un directorio (m+c)
readlink - obtener contenido de un enlace simblico (mc)
reboot - reiniciar o controlar combinacin CTRL-ALT-DEL (-mc)
recv - recibir mensaje de socket conectado (m!c)
recvfrom - recibir mensaje de socket (m!c)
rename - mover/renombrar fichero (m+c)
rmdir - borrar directorio vacio (m+c)
sbrk - ver brk (mc!)
select - dormir hasta actividad en un descriptor de fichero (mc)
semctl - control de semforos ipc (m!c)
semget - obtener id. de semforo ipc (m!c)
semop - operaciones en conjunto de semforos ipc (m!c)
send - enviar mensaje a un socket conectado (m!c)
sendto - enviar mensaje a un socket (m!c)
setdomainname - ajustar dominio del sistema (mc)
setfsgid - ajustar id. grupo del sistema de ficheros ()
setfsuid - ajustar id. usuario del sistema de ficheros ()
setgid - ajustar id. real de grupo (gid) (m+c)
setgroups - ajustar grupos adicionales (mc)
sethostid - ajustar identificador de huesped (mc)
sethostname - ajustar nombre de huesped (mc)
setitimer - ajustar temporizador (mc)
setpgid - ajustar id. de grupo padre (m+c)
setpgrp - sin efecto (mc!)
setpriority - ajustar prioridad de proceso/usuario/grupo (mc)
setregid - ajustar id. de grupo real/efectivo (mc)
setreuid - ajustar id. de usuario real/efectivo (mc)
setrlimit - ajustar limites para los recursos (mc)
setsid - crear sesin (+c)
setsockopt - cambiar opciones del socket (mc)
settimeofday - poner la hora en segundos desde 1970 (mc)
setuid - ajustar id. de usuario real (m+c)
setup - iniciar dispositivos y montar la raiz (-)
sgetmask - ver siggetmask (m)
shmat - enganchar memoria a un segm. de memoria compartida (m!c)
shmctl - manipulacin de mem. compartida ipc (m!c)
shmdt - liberar memoria compartida en un segmento (m!c)
shmget - obtener/crear segmento de memoria compartida (m!c)
shutdown - desconectar socket (m!c)
sigaction - obtener/ajustar manejador de seales (m+c)
sigblock - bloquear seales (m!c)
siggetmask - obtener seales bloqueadas (!c)
signal - poner manejador de seal (mc)
sigpause - usar nueva mascara de seales hasta la prxima seal (mc)
sigpending - obtener seales bloqueadas pendientes (m+c)
sigprocmask - obtener/ajustar mascara de bloqueos de seales (+c)
33 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
sigreturn - no usada aun ()
sigsetmask - ajustar mascara de bloqueos de seales (c!)
sigsuspend - reemplaza a sigpause (m+c)
sigvec - ver sigaction (m!)
socket - crea un extremo de comunicacin para socket (m!c)
socketcall - llamada general de sockets (-)
socketpair - crea dos sockets conectados (m!c)
ssetmask - ver sigsetmask (m)
stat - obtener estado del fichero (m+c)
statfs - obtener estado del sistema de ficheros (mc)
stime - obtener segundos desde 1.1.1970 (mc)
stty - no implementada aun ()
swapo_ - detener el intercambio con un dispositivo o fichero (m-c)
swapon - iniciar el intercambio con un dispositivo o fichero (m-c)
symlink - crear un enlace simblico (m+c)
sync - volcar bloques modificados a disco (mc)
syscall - ejecutar llamada al sistema (-!c)
sysconf - obtener valor de una variable del sistema (m+!c)
sysfs - obtener info. sobre sistemas de ficheros usados ()
sysinfo - obtener info. sobre el sistema (m-)
syslog - manipulacin del registro (m-c)
system - ejecutar un comando de shell (m!c)
time - obtener segundos desde 1.1.1970 (m+c)
times - obtener tiempos del proceso (m+c)
truncate - cambiar tamao de un fichero (mc)
ulimit - obtener/ajustar limites de fichero (c!)
umask - ajustar mascara de creacin de ficheros (m+c)
umount - desmontar un sistema de ficheros (mc)
uname - obtener info. del sistema (m+c)
unlink - borrar un fichero no bloqueado (m+c)
uselib - usar librera compartida (m-c)
ustat - no implementada anu (c)
utime - modificar informacin de acceso de un nodo-i (m+c)
utimes - ver utime (m!c)
vfork - er fork (m!c)
vhangup - colgar virtualmente el terminal actual (m-c)
vm86 - entrar en modo vm86 (m-c)
wait - esperar terminacin de proceso (m+!c)
wait3 - espera terminacin de un proceso (bsd) (m!c)
wait4 - espera terminacin de un proceso (bsd) (mc)
waitpid - espera terminacin de un proceso (m+c)
write - escribir datos a un fichero (m+c)
writev - escribir bloques de datos a un fichero (m!c)
Referencia:
(m) hay pgina de manual.
(+) cumple norma POSIX.
(-) Especfica de Linux.
(c) de libc.
(!) no es solo una llamada al sistema. Usa otras

34 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Bibliografa:
CARRETERO PREZ J., ANASAGASTI PEDRO DE MIGUEL, GARCA CARBALLERIRA F., PREZ COSTOYA F.
Sistemas Operativos, Una visin aplicada. Editorial McGraw Hill. Espaa 2001. ISBN 84-481-3001-4.Proyecto LUCas Gua de programacin de Linux (GULP).Documentacin Oficial de Linux Pginas Man.MARK MITCHELL, JEFFREY OLDHAM, ALEX SAMUEL Advanced Linux Programming First Edition ISBN 07357-1043-0 New Riders Publishing United State of America, June, 2001.-

35 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
APNDICE:
Descriptor de archivo:
Antes de que un archivo pueda leerse o escribir en l, debe abrirse, momento en el cual se verifican los permisos. Si se
permite el acceso, el sistema regresa un entero pequeo llamado descriptor de archivo o entrada de manejo para
usarlos en las operaciones subsecuentes. Si se prohbe el acceso, se regresa un cdigo de error.
Descriptor de archivo en UNIX:
Cuando se abre un archivo en UNIX, se devuelve un descriptor de archivo, que se usa a partir de ese momento para
identificar al archivo en otras llamadas al sistema. Esto descriptores son nmeros enteros de 0 a n y son especficos
para cada proceso. Cada proceso tiene su tabla de descriptores de archivo (tda), desde la que se apunta a los
descriptores internos de los archivos. El descriptor de archivo fd indica el lugar en la tabla, que se rellena de forma
ordenada, de manera que siempre se ocupa la primera posicin libre de la misma. cuando se realiza una operacin
open, el sistema de archivos busca desde la posicin 0 hasta que encuentra una posicin libre, siendo esa la ocupada.
Cuando se cierra un archivo (close), se libera la entrada correspondiente.
Cuando se ejecuta una llamada fork se duplica la PCB del proceso. cuando se cambia la imagen de un proceso con la
llamada exec, uno de los elementos de la PCB que se conserva es la tabal de descriptores de archivos. Pro lo tanto,
basta con que un proceso coloque adecuadamente los descriptores estndar y que luego invoque la ejecucin del
mencionado programa, para que ste utilice los archivo previamente seleccionados.
ipc - Mecanismos de comunicacin entre procesos del System V (Pginas man)
SINOPSIS
# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/msg.h>
# include <sys/sem.h>
# include <sys/shm.h>
DESCRIPCIN
Esta pgina del manual hace referencia a la implementacin en Linux de los mecanismos de comunicacin entre
procesos del System V (IPC, Inter Process Communication): colas de mensajes, conjuntos de semforos y segmentos
de memoria compartida. En la siguiente descripcin, la palabra recurso se refiere a la instancia de uno de dichos
mecanismos.
Permisos de Acceso a Recursos
Para cada recurso el sistema utiliza una estructura de datos comn de tipo struct ipc_perm para almacenar informacin
necesaria para determinar permisos al ejecutar una operacin ipc. La estructura ipc_perm, definida en el fichero de
cabecera <sys/ipc.h> incluye los siguientes miembros:
ushort cuid; /* id del usuario creador */
ushort cgid; /* id de grupo del usuario creador */
ushort uid; /* id del usuario dueo */
ushort gid; /* id de grupo del usuario dueo */
ushort mode; /* permisos de lectura/escritura */
El miembro mode de la estructura ipc_perm define, con los 9 bits ms bajos, los persmisos de acceso al recurso
para cualquier proceso que realice una llamada ipc al sistema. Los permisos se interpretan de la siguiente manera:
0400 Lectura para el usuario.
0200 Escritura para el usuario.
0040 Lectura para el grupo.
36 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
0020 Escritura para el grupo.
0004 Lectura para otros.
0002 Escritura para otros.
Los bits 0100, 0010 y 0001 (bits de ejecucin) no se utilizan. Adems, "write" (permiso de escritura) se interpreta
efectivamente como "alter" (permiso de alteracin) para un conjunto de semforos.
El mismo fichero de cabecera del sistema tambin define las siguientes constantes simblicas:
IPC_CREAT
Crea la entrada si la clave no existe.
IPC_EXCL
Falla si la clave existe.
IPC_NOWAIT Devuelve error si la peticin debe esperar.
IPC_PRIVATE Clave privada.
IPC_RMID
Elimina el recurso.
IPC_SET
Establece opciones del recurso.
IPC_STAT
Obtiene opciones del recurso.
Ntese que IPC_PRIVATE es de tipo key_t, mientras que las otras constantes simblicas son campos sealizadores
que pueden combinarse usando operaciones 'or' en una variable de tipo int.
Colas de Mensajes
Una cola de mensajes se identifica unvocamente usando un nmero entero positivo (llamado msqid) y tiene una
estructura de datos asociada de tipo struct msquid_ds, definida en <sys/msg.h>. La estructura contiene los
siguientes miembros:
struct ipc_perm msg_perm;
ushort msg_qnum; /* nmero de mensajes en cola */
ushort msg_qbytes; /* mximo nmero de bytes en cola */
ushort msg_lspid; /* pid ltima llamada a msgsnd */
ushort msg_lrpid; /* pid ltima llamada a msgrcv */
time_t msg_stime; /* hora ltima llamada a msgsnd */
time_t msg_rtime; /* hora ltima llamada a msgrcv */
time_t msg_ctime; /* hora del ltimo cambio */
msg_perm

ipc_perm estructura que especifica los permisos de acceso a la cola de mensajes.

msg_qnum Nmero actual de mensajes en la cola de mensajes.


msg_qbytes Mximo nmero de bytes permitidos en el texto del mensaje en la cola de mensajes.
msg_lspid ID del proceso que ejecut la ltima llamada a msgsnd.
msg_lrpid ID del proceso que ejecut la ltima llamada a msgrcv.
msg_stime Hora de la ltima llamada a msgsnd.
msg_rtime Hora de la ltima llamada a msgrcv.
msg_ctime Hora de la ltima llamada que cambi un miembro de la estructura msqid_ds.

37 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Conjuntos de Semforos
Un conjunto de semforos se identifica unvocamente usando un nmero entero positivo (llamado semid) y tiene
asociada la siguiente estructura de datos de tipo struct semid_ds, definida en <sys/sem.h>. La estructura contiene los
siguientes campos:
struct ipc_perm sem_perm;
time_t sem_otime; /* hora de la ltima operacin */
time_t sem_ctime; /* hora del ltimo cambio */
ushort sem_nsems; /* cantidad de semforos en el conjunto */
sem_perm ipc_perm estructura que especifica los permisos de acceso al conjunto de semforos.
sem_otime Hora de la ltima llamada a semop.
sem_ctime Hora de la ltima llamada a semctl que cambi un miembro de la estructura anterior o un miembro de
algn semforo del conjunto.
sem_nsems Cantidad de semforos en el conjunto. Cada semforo en el conjunto se accede usando un entero
positivo en el rango 0 a sem_nsems-1.
Un semforo es una estructura de datos de tipo struct sem que contiene los siguientes miembros:
ushort semval; /* valor del semforo */
short sempid; /* pid para la ltima operacin */
ushort semncnt; /* cantidad de semval esperando a ser incrementados */
ushort semzcnt; /* cantidad de semforos esperando cuyo semval = 0 */
semval Valor del semforo: un entero no negativo.
sempid ID del ltimo proceso que realiz una operacin de semforo sobre este semforo.
semncnt Cantidad de procesos suspendidos esperando que semval aumente.
semznt
Cantidad de procesos suspendidos esperando que semval se haga cero.
Segmentos de Memoria Compartida
Un segmento de memoria compartida se identifica unvocamente mediante un nmero entero positivo (llamado
shmid) y tiene una estructura de datos asociada de tipo struct shmid_ds, definida en <sys/shm.h>. La estructura
contiene los siguiente miembros:
struct ipc_perm shm_perm;
int shm_segsz;
/* Tamao del segmento */
ushort shm_cpid;
/* pid del creador */
ushort shm_lpid;
/* pid de la ltima operacin */
short shm_nattch; /* cantidad actual de conexiones */
time_t shm_atime; /* hora de la ltima conexion */
time_t shm_dtime; /* hora ltima desconexin */
time_t shm_ctime; /* hora del ltimo cambio */
shm_perm

ipc_perm estructura que especifica los permisos de acceso al segmento de memoria compartida.

shm_segsz Tamao en bytes del segmento de memoria compartida.


shm_cpid

ID del proceso que creo el segmento de memoria compartida.

shm_lpid

ID del ltimo proceso que ejecut una llamada del sistema shmat o shmdt.
38 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
shm_nattch Cantidad de conexiones activas actualmente para este segmento de memoria compartida.
shm_atime Hora de la ltima llamada a shmat.
shm_dtime Hora de la ltima llamada a shmdt.
shm_ctime Hora de la ltima llamada a shmctl que cambi shmid_ds.
VASE TAMBIN
ftok(3), msgctl(2), msgget(2), msgrcv(2), msgsnd(2), semctl(2), semget(2), semop(2), shmat(2), shmctl(2),
shmget(2), shmdt (2).

NOMBRE
semctl - operaciones de control de semforos
SINOPSIS
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* la union semun se define al incluir <sys/sem.h> */
#else
/* segn X/OPEN tenemos que definirla nosostros mismos */
union semun {
int val;
/* valor para SETVAL */
struct semid_ds *buf;
/* buffer para IPC_STAT, IPC_SET */
unsigned short int *array; /* array para GETALL, SETALL */
struct seminfo *__buf;
/* buffer para IPC_INFO */
};
#endif
int semctl (int semid, int semnun, int cmd, union semun arg)
DESCRIPCIN
La funcin realiza la operacin de control especificada por cmd en el conjunto de semforos (o en el semforo
semnum-avo del grupo) identificado por semid. El primer semforo del conjunto est indicado por el valor 0 para
semnum.
Valores vlidos para cmd son:
IPC_STAT Copiar informacin de la estructura de datos del conjunto de semforos en la estructura apuntada
por arg.buf. El argumento semnum es ignorado. El proceso que realiza la llamada debe tener privilegios de acceso de
lectura en el conjunto de semforos.

39 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
IPC_SET
Escribir los valores de algunos miembros de la estructura semid_ds apuntada por arg.buf a la
estructura de datos del conjunto de semforos, actualizando tambin su miembro sem_ctime. Los miembros de la
estructura provista por el usuario struct semid_ds a los que apunta arg.buf son
sem_perm.uid
sem_perm.gid
sem_perm.mode

/* solo los 9 bits ms bajos */

El ID de usuario efectivo del proceso que realiza la llamada debe ser o de super-usuario, o el del creador o propietario
del conjunto de semforos. El argumento semnum es ignorado.
IPC_RMID Borrar inmediatamente el conjunto de semforos y sus estructuras de datos, despertando todos los
procesos en espera (devuelve un error, y errno puesto a EIDRM). El ID de usuario efectivo del proceso que realiza
la llamada debe ser o de super-usuario, o el del creador o propietario del conjunto de semforos. El argumento
semnum es ignorado.
GETALL
Devuelve semval para todos los semforos del conjunto, en arg.array. El argumento semnum es
ignorado. El proceso que realiza la llamada ha de tener privilegios de lectura en el conjunto de semforos.
GETNCNT
La llamada al sistema devuelve el valor de semncnt para el semnum-avo semforo del conjunto
(p.ej. el nmero de procesos esperando que aumente semval para el semnum-avo semforo del conjunto). El proceso
que realiza la llamada ha de tener privilegios de lectura en el conjunto de semforos.
GETPID
La llamada al sistema devuelve el valor de sempid para el semnum-avo semforo del conjunto (p.ej.
el pid del proceso que ejecut la ltima llamada semop para el semnum-avo semforo del conjunto). El proceso que
realiza la llamada ha de tener privilegios de lectura en el conjunto de semforos.
GETVAL
La llamada al sistema devuelve el valor de semval para el semnum-avo semforo del conjunto. El
proceso que realiza la llamada ha de tener privilegios de lectura en el conjunto de semforos.
GETZCNT
La llamada al sistema devuelve el valor de semzcnt para el semnum-avo semforo del conjunto
(p.ej. el nmero de procesos que esperan que semval del semnum-avo semforo del conjunto se ponga a 0). El
proceso que realiza la llamada ha de tener privilegios de lectura en el conjunto de semforos.
SETALL
Poner semval para todos los semforos del conjunto usando arg.array, actualizando tambin el
miembro sem_ctime de la estructura semid_ds asociada al conjunto. Los registros de anulacin son limpiados, para
los semforos cambiados, en todos los procesos. Los procesos que estn durmiendo en la cola de espera son
despertados si algn semval se pone a 0 o se incrementa. El argumento semnum es ignorado. El proceso que realiza
la llamada ha de tener privilegios de modificacin en el conjunto de semforos.
SETVAL
Poner el valor de semval a arg.val para el semnum-avo semforo del conjunto, actualizando
tambin el miembro sem_ctime de la estructura semid_ds asociada al conjunto. El registro de anulacin es limpiado,
para el semforo alterado, en todos los procesos. Los procesos que estn durmiendo en la cola de espera son
despertados si semval se pone a 0 o se incrementa. El proceso que realiza la llamada ha de tener privilegios de
escritura en el conjunto de semforos.
VALOR DEVUELTO
Si falla, la llamada al sistema devuelve -1, mientras errno indica el error. De otro modo, la llamada al sistema
devuelve un valor no negativo, dependiendo de cmd como sigue:
GETNCNT el valor de semncnt.
GETPID
el valor de sempid.
GETVAL
el valor de semval.
40 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
GETZCNT

el valor de semzcnt.

ERRORES
EACCESS
El proceso que realiza la llamada no tiene los permisos necesarios para ejecutar cmd.
EFAULT
La direccin a la que apunta arg.buf o arg.array no es accesible.
EIDRM
El conjunto de semforos se borr.
EINVAL
Valor no vlido para cmd o semid.
EPERM
El argumento cmd tiene valor IPC_SET o IPC_RMID pero el user-ID del proceso que realiza la llamada no tiene
suficientes privilegios para ejecutar el comando.
ERANGE
El argumento cmd tiene el valor SETALL o SETVAL y el valor al que ha de ser puesto semval (para algn semforo del
conjunto) es menor que 0 o mayor que el valor SEMVMX de la implementacin.
NOTAS
Las llamadas de control IPC_INFO, SEM_STAT y SEM_INFO son utilizadas por el programa ipcs(8) para proveer
informacin sobre recursos asignados. En el futuro pueden ser modificadas segn se necesite, o llevadas al interfaz del
sis

NOMBRE
semget - obtiene el identificador de un conjunto de semforos
SINOPSIS
# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/sem.h>
int semget ( key_t key, int nsems, int semflg )
DESCRIPCIN
La funcin devuelve el identificador del conjunto de semforos asociado al valor del argumento key. Un nuevo
conjunto de nsems semforos se crea si key tiene el valor IPC_PRIVATE, o si key no vale IPC_PRIVATE, no hay un
conjunto de semforos asociado a key, y el bit IPC_CREAT vale 1 en semflg (p.ej. semflg & IPC_CREAT es distinto de
cero). La presencia en semflg de los campos IPC_CREAT e IPC_EXCL tiene el mismo papel, con respecto a la existencia
del conjunto de semforos, que la presencia de O_CREAT y O_EXCL en el argumento mode de la llamada del sistema
open(2): p.ej., la funcin semget falla si semflg tiene a 1 tanto IPC_CREAT como IPC_EXCL y ya existe un conjunto de
semforos para key.
Acerca de la creacin, los 9 bits bajos del argumento semflg definen los permisos de acceso (para el propietario,
grupo y otros) al conjunto de semforos en el mismo formato, y con el mismo significado, que para el parmetro de
permisos de acceso en las llamadas al sistema open(2) o creat(2) (aunque los permisos de ejecucin no son usados por
el sistema, y los de escritura, para un conjunto de semforos, efectivamente significa permisos de modificacin).

41 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Adems, durante la creacin, la llamada al sistema inicializa la estructura de datos semid_ds del conjunto
semforos del sistema, como sigue:

de

Se pone el ID de usuario efectivo del proceso que realiza la llamada en sem_perm.cuid y sem_perm.uid
Se pone el ID de grupo efectivo del proceso que realiza la llamada en sem_perm.cgid y sem_perm.gid
Los 9 bits ms bajos de sem_perm.mode se ponen como los 9 bits ms bajos de semflg.
Se pone el valor de nsems en sem_nsems.
sem_otime se pone a 0.
Se pone la hora actual en sem_ctime.
El argumento nsems puede ser 0 (un comodn o valor sin importancia) cuando la llamada del sistema no es de
creacin. En otro caso nsems debe ser mayor que 0 y menor o igual que el nmero mximo de semforos por semid,
(SEMMSL).
Si el conjunto de semforos ya existe, los permisos de acceso son verificados, y se hace una comprobacin para ver si
est marcado para ser destruido.
VALOR REGRESADO
Si hubo xito, el valor devuelto ser el identificador del conjunto de semforos (un entero positivo), de otro modo,
se devuelve -1 con errno indicando el error.
ERRORES
EACCES
Existe un conjunto de semforos para key, pero el proceso que realiza la llamada no tiene permisos de acceso al
conjunto.
EEXIST
Existe un conjunto de semforos para key y semflg tiene a 1 tanto IPC_CREAT como IPC_EXCL.
EIDRM
El conjunto de semforos est marcado para ser borrado.
ENOENT
No existe ningn conjunto de semforos para key y semflg no tiene a 1 IPC_CREAT.
ENOMEM
Se ha de crear un conjunto de semforos, pero el sistema no tiene suficiente memoria para la nueva estructura de
datos.
ENOSPC
Se ha de crear un conjunto de semforos, pero el lmite del sistema para el nmero mximo de conjuntos de semforos
(SEMMNI), o el nmero de semforos mximo del sistema (SEMMNS), sera excedido.
NOTAS
IPC_PRIVATE no es un campo bandera (flag), sino que es de tipo key_t Si este valor especial es usado para key,
la llamada del sistema ignora todo excepto los 9 bits ms bajos de semflg y crea un nuevo conjunto de semforos (si
hay xito).
42 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Los siguientes son lmites de los recursos de los conjuntos de semforos que afectan a la llamada semget :
SEMMNI
Mximo total de conjuntos de semforos para el sistema: depende de la poltica.
SEMMSL
Mximo de semforos por semid: depende de la implementacin (500 normalmente).
SEMMNS
Mximo total de semforos para el sistema: depende de la poltica. Valores mayores que SEMMSL * SEMMNI lo hacen
irrelevante.
FALLOS
El uso de IPC_PRIVATE no inhibe el acceso de los dems procesos al conjunto de semforos asignado.
Al igual que pasa con los ficheros, no hay una manera intrnseca para que un proceso se asegure el acceso
exclusivo a un conjunto de semforos. Tener a 1 tanto IPC_CREAT como IPC_EXCL en semflg solo asegura (si hay
xito) la creacin de un nuevo conjunto de semforos, no implica acceso exclusivo a dicho conjunto.
La estructura de datos asociada con cada semforo del conjunto no es inicializada por la llamada del sistema. Para
inicializar estas estructuras de datos, se ha de ejecutar la subsiguiente llamada a semctl(2) para realizar un comando
SETVAL o SETALL en el conjunto de semforos.
CONFORME A
SVr4, SVID. SVr4 documenta condiciones de error adicionales EINVAL, EFBIG, E2BIG, EAGAIN, ERANGE, EFAULT.
VASE TAMBIN
ftok(3), ipc(5), semctl(2), semop(2)

NOMBRE
semop - operaciones con semforos
SINTAXIS
# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/sem.h>
int semop ( int semid, struct sembuf *sops, unsigned nsops )
DESCRIPCIN
Esta funcin ejecuta operaciones en los miembros seleccionados del semforo indicado por semid. Cada uno de los
nsops elementos en el array apuntado por sops especifica una operacin a ser realizada en un semforo por struct
sembuf incluyendo los siguientes miembros:
short sem_num; /* numero de semforo: 0 = primero */
short sem_op; /* operacin sobre el semforo */
short sem_flg; /* banderas (indicadores/parametros) de la operacin */

43 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
Banderas reconocidas en sem_flg son IPC_NOWAIT y SEM_UNDO.
deshecha cuando el proceso finalice.

Si una operacin

ejecuta SEM_UNDO, sera

La semntica de la llamada al sistema asegura que la operacin er ejecutada si y solo si todas ellas pueden ser
ejecutadas. Cada operacin es ejecutada en el semforo numero sem_num donde el primer semforo del conjunto es
el semforo 0 - y es uno entre los siguientes tres.
Si sem_op es un entero positivo, la operacin aade este valor a semval. Sin embargo, si SEM_UNDO es invocado
para esta operacin , el sistema actualiza el contador del proceso (para operaciones "undo") para este semforo. La
operacin siempre se ejecuta, por lo que no puede haber ningn proceso durmiendo. El proceso que invoca debe
tener los permisos modificados en el conjunto de semforos.
Si sem_op es cero, el proceso debe tener permiso de lectura en el semforo. Si semval es cero, la operacin se
ejecuta. Por otra parte, si IPC_NOWAIT es invocado en sem_flg, la llamada al sistema falla (deshaciendo todas las
acciones anteriores ejecutadas) con la variable errno fijada a EAGAIN. En otro caso semzcnt es incremetada en uno
y el proceso duerme hasta que algo de lo siguiente ocurra:

semval es 0, instante en el que el valor de semzcnt es decrementeado.


El semforo es eliminado: la llamada al sistema falla con errno fijada a EIDRM.
El proceso que lo invoca recibe una seal que debe ser atendida: el valor de semzcnt es decrementado y la llamada
al sistema falla con errno fijada a EINTR.
Si sem_op es menor que cero, el proceso debe tener los permisos de modificacin sobre el semforo. Si semval es
mayor que o igual que el valor absoluto de sem_op, el valor absoluto de sem_op es restado a semval. Por otra
parte, si SEM_UNDO es invocado para esta operacin, el sistema actualiza el contador "undo" del pro ceso para este
semforo. Entonces la operacin se ejecuta. En otro caso, si IPC_NOWAIT es invocado en sem_flg, la llamada al
sistema falla (deshaciendo todas las acciones anteriores ejecutadas) con errno fijado a EAGAIN. En otro caso semncnt
es incrementado en uno y el proceso duerme hasta que ocurra:
sea mayor o igual que el valor absoluto de sem_op, en cuyo instante el valor de semncnt es decrementado, el valor
absoluto de sem_op es restado de semval y, si SEM_UNDO es invocado para esta operacin , el sistema actualiza el
contador "undo" del proceso para este semforo.
El semforo es eliminado del sistema: la llamada al sistema falla con errno fijado a EIDRM.
El proceso invocador recibe una seal que tiene que capturar: el valor de semncnt es decrementado y la llamada al
sistema falla con errno fijado a EINTR.
En caso de que haya funcionado, el miembro sempid de la estructura sem para cada semforo especificado en el array
apuntado por sops es fijado al identificador del proceso del proceso que la invoca. De otra forma sem_otime y
sem_ctime son fijados a la hora actual.
VALOR DEVUELTO
Si todo ha sido correcto la llamada al sistema devuelve 0, en otro caso devuelve
-1 con errno indicando el error.
ERRORES
E2BIG
44 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
El argumento nsops es mayor que SEMOPM, el numero mximo de operaciones permitidas por llamada del sistema.
EACCES
El proceso invocador no tiene permisos de acceso al semforo como se requiere por una de las operaciones
especificadas.
EAGAIN
Una operacin no puede ser ejecutada y IPC_NOWAIT ha sido invocada en su sem_flg.
EFAULT
La direccin apuntada por sops no es accesible.
EFBIG
Para algunas operaciones el valor de sem_num es menor que 0 o mayor o igual que el numero de semforos en el
conjunto.
EIDRM
El conjunto de semforos ha sido eliminado.
EINTR
Durmiento en una cola de espera, el proceso recibio una seal que debe ser capturada.
EINVAL
Este conjunto de semforos no existe, o semid es menor que cero, o nsops tiene un valor no-positivo.
ENOMEM
El sem_flg de alguna operacin invoco SEM_UNDO y el sistema no tiene suficiente memoria para alojar la estructura
"undo".
ERANGE
Para alguna operacin semop+semval es mayor que SEMVMX, el valor mximo dependiente de la implementacin para
semval.
ANUNCIA
La estructura sem_undo de un proceso no es heredada por sus hijos en la ejecucin de fork(2) Son, en cambio,
heredadas por el proceso sustituto resultante de la ejecucin de execve(2)
Los siguientes valores son limites en el conjunto de recursos de los semforos que afecta a semop:
SEMOPM
Numero mximo de operaciones permitidas para una llamada semop, dependiente de la
implementacin.
SEMVMX

Valor mximo permitido para semval: dependiente de la implementacin (32767).

La implementacin no contiene lmites intrnsecos para ajustar el valor mximo de la salida (SEMAEM), el numero
mximo de estructuras "undo" que el sistema permite (SEMMNU) y mximo numero de entradas "undo" por proceso
para los parametros del sistema.
FALLOS
El sistema mantiene una estructura sem_undo por proceso para cada semforo modificado por el proceso con
parmetro "undo". Estas estructuras estn vacas a la terminacin de un proceso. Una causa de insatisfaccin con
el mecanismo "undo" es que no es compatible con la nocin de tener un conjunto atmico de operaciones en un vector
45 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
de semforos. La llamada "undo" para un vector y cada semforo en este deben ser acumuladas en varias llamadas
semopt Debe pasar un proceso al estado dormido cuando ha finalizado, o debe deshacer todas las operaciones realizadas con el parmetro ? IPC_NOWAIT Actualmente estas operaciones "undo" que se invocan son ejecutadas
inmediatamente, y aquellas querequieren una espera son ignoradas en silencio. Luego el uso correcto del "undo"
esta garantizado solo con semforos de tipo pri vado.
COMPATIBLE CON
SVr4, SVID. SVr4 documenta las condiciones de error adicionales EINVAL, EFBIG, ENOSPC.
VASE TAMBIN
ipc(5), semctl(2), semget(2)
NOMBRE
errno - nmero del ltimo error
SINOPSIS
#include <errno.h>
extern int errno;
DESCRIPCIN
Algunas llamadas al sistema (y algunas funciones de biblioteca) dan un valor al
entero errno para indicar qu ha
ido mal. Su valor slo es significativo cuando la
llamada devolvi un error (usualmente -1) y cuando una funcin
de biblioteca que la acabe bien tenga permitido cambiar errno.
Algunas veces, cuando una funcin tambin puede devolver -1 como valor vlido, se debe poner errno a cero antes de
la llamada, para poder detectar posibles errores.
errno se define en el estndar ISO de C como un lvalor (valor de lado izquierdo) modificable de tipo int y no se debe
declarar de forma explcita; errno puede ser una macro. errno es "local en hilo"; asignarle un valor en un hilo no
afecta al
valor que tenga en ningn otro hilo.
Los nmeros de error vlidos son todos no cero; ninguna funcin de biblioteca asigna nunca un valor cero a errno.
Todos los nombres de error especificados por POSIX.1 deben tener valores distintos.
POSIX.1 (edicin de 1996) lista los siguientes nombres de error simblicos. De stos, EDOM y ERANGE existen en el
estndar ISO de C. La enmienda 1 del ISO C define el nmero de error adicional EILSEQ para codificar los errores
en mltiples bytes o caracteres extendidos.
E2BIG Lista de argumentos demasiado larga
EACCES Permiso denegado
EAGAIN Recurso temporalmente no disponible
EBADF Descriptor de fichero incorrecto
EBADMSG Mensaje incorrecto
EBUSY Recurso ocupado
ECANCELED Operacin cancelada

46 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
ECHILD No hay procesos hijos
EDEADLK Interbloqueo de recurso evitado
EDOM Error de dominio
EEXIST El fichero existe
EFAULT Direccin incorrecta
EFBIG Fichero demasiado grande
EINPROGRESS Operacin en progreso
EINTR Llamada a funcin interrumpida
EINVAL Argumento invlido
EIO

Error de Entrada/Salida

EISDIR Es un directorio
EMFILE Demasiados ficheros abiertos
EMLINK Demasiados enlaces
EMSGSIZE Longitud de buffer de mensaje inapropiada
ENAMETOOLONG Nombre de fichero demasiado largo
ENFILE Demasiados ficheros abiertos en el sistema
ENODEV No existe tal dispositivo
ENOENT No existe ese fichero o directorio
ENOEXEC Error en el formato del ejecutable
ENOLCK No hay bloqueos disponibles
ENOMEM No hay bastante espacio
ENOSPC No queda espacio en el dispositivo
ENOSYS Funcin no implementada
ENOTDIR No es un directorio
ENOTEMPTY El directorio no est vaco
ENOTSUP Operacin no soportada
ENOTTY Operacin de control de E/S inapropiada
47 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

SISTEMAS OPERATIVOS II
ENXIO No existe tal dispositivo o direccin
EPERM Operacin no permitida
EPIPE Interconexin rota
ERANGE Resultado demasiado grande
EROFS Sistema de ficheros de slo lectura
ESPIPE Posicionamiento invlido
ESRCH No existe tal proceso
ETIMEDOUT La operacin ha excedido su plazo de tiempo
EXDEV Enlace inapropiado
Otras implementaciones de Unix devuelven muchos otros tipos de error. System V devuelve ETXTBSY (fichero de
cdigo ocupado) si se intenta ejecutar una llamada exec() sobre un fichero que actualmente est abierto para
escritura.
Linux tambin devuelve este error si se intenta tener un fichero tanto asociado en memoria con
VM_DENYWRITE como abierto para escritura.

NOMBRE
strerror - devuelve una cadena de caracteres describiendo un cdigo de error
SINOPSIS
#include <string.h>
char *strerror(int errnum);
DESCRIPCIN
La funcin strerror() devuelve una cadena de caracteres que describe el cdigo de error pasado en el argumento
errnum. La cadena slo puede ser usada hasta la siguiente llamada a strerror().
VALOR DEVUELTO
La funcin strerror() devuelve la cadena apropiada que describe el error, o un mensaje de error desconocido si el
cdigo de error es invlido.
CONFORME A
SVID 3, POSIX, BSD 4.3, ISO 9899

48 DE 48 CTEDRA S ISTEMAS OPERATIVOS II 2006

También podría gustarte