164
IPC : SEMÁFOROS. Carmelo Quintana Hernández, [email protected] Miguel Ramírez Alemán [email protected]

IPC : SEMÁFOROS. Carmelo Quintana Hernández, [email protected] [email protected] Miguel Ramírez Alemán [email protected]

Embed Size (px)

Citation preview

Page 1: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

IPC : SEMÁFOROS.

Carmelo Quintana Hernández, [email protected]

Miguel Ramírez Alemá[email protected]

Page 2: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Índice. Conceptos.

Semáforos Tabla de Semáforos.

Estructuras de Datos. Semid_ds Sembuf Semun Seminfo

Llamadas al Sistema. Semget Semop Semctl

Ejemplo Práctico.

Código Fuente.

Page 3: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

CONCEPTOSSemáforo.

Tabla de Semáforos.

Page 4: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semáforos.

Para la gente de la calle los semáforos no son mas que los postes indicadores que tienen luces verde, roja o naranja que regula el tránsito en las vías públicas.

En los S.O. son el mecanismo que se utiliza para prevenir la colisión que se produce cuando dos o más procesos solicitan simultáneamente el uso de un recurso que deben compartir Problema de exclusión mutua.

Page 5: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Tabla de Semáforos.

En algunos casos, un proceso necesita poseer varios recursos para proseguir su acción.

Primera Solución : Disponer de varios semáforos. Problema: Esos semáforos pueden estar siendo utilizados

por otros procesos por lo que se pueden producir interbloqueos.

Solución Final: Las operaciones P y V no se efectúan “atómicamente” con un solo semáforo sino con una tabla de semáforos (TS).

Page 6: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Ejemplo para T.S (1).

Dos procesos deben acceder a memoria intermedia de datos y a un segmento de memoria compartida para desplazar los datos de un lugar a otro.

Page 7: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Ejemplo para T.S (2).

Según la primera solución serán necesarios dos semáforos y ejecute dos operaciones P (una de la memoria intermedia y otra para la memoria) a fin de poder disponer de los dos recursos.

Page 8: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Ejemplo para T.S (3).

Problema: Puede provocarse un bloqueo cruzado en el caso de cada proceso posee el acceso exclusivo a uno de los recursos y ambos quieren acceder al otro recurso a la vez.

Page 9: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Ejemplo para T.S (4).

Solución: Las operaciones P y V se efectúan “atómicamente” con una tabla de semáforos.

Page 10: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

ESTRUCTURAS DE DATOS

Semid_dsSembufSemun

Seminfo

Page 11: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Page 12: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Permisos

Page 13: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Fecha de

última operacion

Page 14: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Fecha del

último cambio

por semctl

Page 15: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Puntero al

primer semáforo del grupo

Page 16: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Operaciones en

Espera de

realización

Page 17: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Última Operaciónen espera

Page 18: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Operaciones anuladas

en caso de terminación

Page 19: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semid_ds.

struct semid_ds { struct ipc_perm sem_perm; __kernel_time_t sem_otime; __kernel_time_t sem_ctime; struct sem *sem_base; struct sem_queue *sem_pending; struct sem_queue **sem_pending_last; struct sem_undo *undo; unsigned short sem_nsems; };

Se trata de una estructura de control asociada a cada uno de los distintos conjuntos de semáforos existentes en el sistema. Contiene información del sistema, punteros a las operaciones a realizar sobre el grupo, y un puntero hacia las estructuras sem que se almacenan en el núcleo y contienen información de cada semáforo.

Númerode semáforos

del grupo

Page 20: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Sembuf.

struct sembuf { unsigned short sem_num; short sem_op; short sem_flg; };

Se trata de una estructura que se utiliza en semop, y cada dato de este tipo especifica una operación a realizar sobre un semáforo particular dentro del conjunto. Incrementar, decrementar o esperar un valor nulo y por lo tanto se usa en la llamada semop.

Page 21: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Sembuf.

struct sembuf { unsigned short sem_num; short sem_op; short sem_flg; };

Se trata de una estructura que se utiliza en semop, y cada dato de este tipo especifica una operación a realizar sobre un semáforo particular dentro del conjunto. Incrementar, decrementar o esperar un valor nulo y por lo tanto se usa en la llamada semop.

Númerode semáforosen el grupo

Page 22: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Sembuf.

struct sembuf { unsigned short sem_num; short sem_op; short sem_flg; };

Operacionessobre el

semáforo.

Se trata de una estructura que se utiliza en semop, y cada dato de este tipo especifica una operación a realizar sobre un semáforo particular dentro del conjunto. Incrementar, decrementar o esperar un valor nulo y por lo tanto se usa en la llamada semop.

Page 23: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Sembuf.

struct sembuf { unsigned short sem_num; short sem_op; short sem_flg; }; Opciones.

Se trata de una estructura que se utiliza en semop, y cada dato de este tipo especifica una operación a realizar sobre un semáforo particular dentro del conjunto. Incrementar, decrementar o esperar un valor nulo y por lo tanto se usa en la llamada semop.

Page 24: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semun.

union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; void *__pad;};

Es una unión, se utiliza en la llamada semctl para almacenar o recuperar informaciones sobre los semáforos.

Page 25: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semun.

union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; void *__pad;};

Es una unión, se utiliza en la llamada semctl para almacenar o recuperar informaciones sobre los semáforos.

Valor para SETVAL.

El signo del campo es quien define la acción.

val < 0 op P.val > 0 op V.

Page 26: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semun.

union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; void *__pad;};

Es una unión, se utiliza en la llamada semctl para almacenar o recuperar informaciones sobre los semáforos.

Memoria de datos para

IPC_STAT e IPC_SET.

Page 27: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semun.

union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; void *__pad;};

Es una unión, se utiliza en la llamada semctl para almacenar o recuperar informaciones sobre los semáforos.

Tabla para GETALL y

SETALL

Page 28: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semun.

union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; void *__pad;};

Es una unión, se utiliza en la llamada semctl para almacenar o recuperar informaciones sobre los semáforos.

Memoria de datos para

IPC_INFO

Page 29: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semun.

union semun { int val; struct semid_ds *buf; unsigned short *array; struct seminfo *__buf; void *__pad;};

Es una unión, se utiliza en la llamada semctl para almacenar o recuperar informaciones sobre los semáforos.

Puntero de alineación

de la estructura

Page 30: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

Page 31: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

No se usan.

Page 32: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

Número máximo

de grupos de semáforos

(SEMMI = 128)(IPC_INFO)

Page 33: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

Número máximo de semáforos

(SEMMNS=SEMMI * SEMMSL)(IPC_INFO)

Page 34: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

Número máximo

de semáforos por grupo

(SEMMSL=32)(IPC_INFO)

Page 35: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

Número de grupos de semáforos

actualmente Definidos

(SEMINFO)

Page 36: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

Valor máximo del contador de semáforos

(SEMVMX=32767)(IPC_INFO)

Page 37: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Seminfo.struct seminfo { int semmap; int semmni; int semmns; int semmnu; int semmsl; int semopm; int semume; int semusz; int semvmx; int semaem;};

Almacena información sobre los semáforos, mas concretamente sobre el número de conjunto de semáforos, semáforos declarados, en uso, y los limites.

Número de semáforos

actualmente definidos

(SEMINFO)

Page 38: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

LLAMADAS AL SISTEMA

Semget

Semop

Semctl

Page 39: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semget (1).

Permite la creación de un grupo de semáforos, o bien la recuperación del identificador de un grupo ya existente.

El grupo de semáforos esta unificado bajo un identificador común.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semget (key_t key, int nsems, int semflg);

Page 40: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semget (2).

Parámetros:

key : identificador de los semáforos o “clave” para la creación de un nuego grupo de semáforos.

IPC_PRIVATE Key

nsem : cantidad de semáforos en el recurso. semflg: bandera de opciones

IPC_CREAT IPC_EXCL Permisos

Valor retornado:

Éxito identificador del semáforo creado

Error -1 y en errno.

Page 41: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semget (3).

Descripción: semget devuelve el identificador del semáforo

correspondiente a la clave key. Puede ser un semáforo ya existente O bien semget crea uno nuevo si se da alguno de estos casos:

• key vale IPC_PRIVATE. Este valor especial obliga a semget a crear un nuevo y único identificador, nunca devuelto por ulteriores llamadas a semget hasta que sea liberado con semctl.

• key no está asociada a ningún semáforo existente, y se cumple que (semflg & IPC_CREAT) es cierto.

semflg es una máscara que puede contener IPC_CREAT, que ya hemos visto, o IPC_EXCL, que hace crear el semáforo, pero fracasando si ya existía.

En sus ultimos 9 bits residen los permisos estilo UNIX de acceso al semáforo (usuario, grupo, otros).

Page 42: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semget (3).

Descripción: semget devuelve el identificador del semáforo

correspondiente a la clave key. Puede ser un semáforo ya existente O bien semget crea uno nuevo si se da alguno de estos casos:

• key vale IPC_PRIVATE. Este valor especial obliga a semget a crear un nuevo y único identificador, nunca devuelto por ulteriores llamadas a semget hasta que sea liberado con semctl.

• key no está asociada a ningún semáforo existente, y se cumple que (semflg & IPC_CREAT) es cierto.

semflg es una máscara que puede contener IPC_CREAT, que ya hemos visto, o IPC_EXCL, que hace crear el semáforo, pero fracasando si ya existía.

En sus ultimos 9 bits residen los permisos estilo UNIX de acceso al semáforo (usuario, grupo, otros).

Page 43: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semget (4).

int semid = semget ( IPC_PRIVATE, 1, IPC_CREAT | 0744 );

Ejemplo:

Crea un único nuevo semáforo con identificador único con accesos de todos los permisos para el usuario y solo lectura para grupo y otros.

IPC_CREAT está únicamente para asegurar que no está asociada a ningún semáforo existente, aunque no hace falta porque ya IPC_PRIVATE se encarga de eso

Page 44: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semop (1).

Para realizar las operaciones sobre los semáforos que hay asociados bajo un identificador.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semop(int semid, struct sembuf *tsops,

unsigned nsops);

Page 45: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semop (2).

Parámetros:

semid es el identificador del semáforo sops es un apuntador a un vector de operaciones de tipo

sembuf. nsops indica el número de operaciones solicitadas.

Valor retornado:

Éxito El valor del ultimo semáforo sobre el cual se realizó la ultima operación.

Error -1 y en errno el error.

Page 46: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semop (3).

Descripción:

Si el campo semop de la estrcutura sembuf de una operación es: Semop > 0: Se suma sem_op al valor del semáforo invocado, y despierta a

todos los procesos que esperan a que este valor aumente a dicho valor. (V)

Semop == null: Comprobación del valor del semáforo, si es nulo se bloquea el proceso.

Semp < 0: Disminuye |sem-op| el valor del semáforo, si no es posible entonces bloquea el proceso. Si el valor alcanzado es cero entonces despierta a los procesos correspondientes. (P)

Todas las operaciones deben efectuarse de manera atómica. En los casos en que esto no sea posible:

• El proceso se suspende hasta que sea posible,• Si IPC_NOWAIT está activado en el campo sem_flg de la estructura sembuf en alguna de

las operaciones, se interrumpe sin realizar ninguna operación.

Por cada operación efectuada, se controla si SEM_UNDO está posicionado. Si es así, crea una estructura para conservar el rastro de esa operación y poder

anularla y finalizar la ejecución del proceso.

Page 47: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semop (3).

Descripción:

Si el campo semop de la estrcutura sembuf de una operación es: Semop > 0: Se suma sem_op al valor del semáforo invocado, y despierta a

todos los procesos que esperan a que este valor aumente a dicho valor. (V)

Semop == null: Comprobación del valor del semáforo, si es nulo se bloquea el proceso.

Semp < 0: Disminuye |sem-op| el valor del semáforo, si no es posible entonces bloquea el proceso. Si el valor alcanzado es cero entonces despierta a los procesos correspondientes. (P)

Todas las operaciones deben efectuarse de manera atómica. En los casos en que esto no sea posible:

• El proceso se suspende hasta que sea posible,• Si IPC_NOWAIT está activado en el campo sem_flg de la estructura sembuf en alguna de

las operaciones, se interrumpe sin realizar ninguna operación.

Por cada operación efectuada, se controla si SEM_UNDO está posicionado. Si es así, crea una estructura para conservar el rastro de esa operación y poder

anularla y finalizar la ejecución del proceso.

Page 48: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semop (4).

struct sembuf sb = {0, -1, 0};

...

result = semop(semid, &sb, 1);

Realizando una operación P

struct sembuf sb = {0, 1, 0};

...

result = semop(semid, &sb, 1);

Realizando una operación V

Page 49: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semctl (1).

Esta llamada al sistema permite la consulta, modificación o supresión de un grupo de semáforos.

También permite inicializar los semáforos y obtener información sobre el número de semáforos en espera de aumento.

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semctl(int semid, int semnum, int cmd,

union semun arg, unsigned nsops);

Page 50: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semctl (2).

Parámetros:

semid: identificador resultado de semget()

semnum: semáforo sobre el cual voy a realizar la operación.

arg: parámetro requerido para realizar la operación indicada (parámetro sólo válido para algunas operaciones).

cmd: operación a realizar (ver a continuación)

Valor retornado:

Éxito 0.

Error -1 y en errno el error.

Page 51: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semctl(3).

Operación a Realizar:

IPC_STAT: carga la estructura semid_ds asociada al recurso en arg

IPC_SET: define los permisos del recurso tomando los valores de arg

GETPID: retorna el identificador del proceso que realiza la última operación.

GETVAL : retorna el valor del semáforo número semnum. GETNCNT: cantidad de procesos esperando que se

incremente el semáforo. GETZCNT : cantidad de procesos esperando que el semáforo

alcance el valor cero. SETVAL: carga el valor del semáforo con arg.val. GETALL: carga el valor de todos los semáforos en arg.array SETALL: carga el valor de todos los semáforos con arg.array IPC_RMID: elimina el recurso compartido.

Page 52: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semctl(3).

Operación a Realizar:

IPC_STAT: carga la estructura semid_ds asociada al recurso en arg

IPC_SET: define los permisos del recurso tomando los valores de arg

GETPID: retorna el identificador del proceso que realiza la última operación.

GETVAL : retorna el valor del semáforo número semnum. GETNCNT: cantidad de procesos esperando que se

incremente el semáforo. GETZCNT : cantidad de procesos esperando que el semáforo

alcance el valor cero. SETVAL: carga el valor del semáforo con arg.val. GETALL: carga el valor de todos los semáforos en arg.array SETALL: carga el valor de todos los semáforos con arg.array IPC_RMID: elimina el recurso compartido.

Page 53: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Semctl(4).

valor = semctl (semid,semnum,GETVAL);

Lee el valor del semáforo semnum perteneciente al grupo semid

semctl (semid,semnum,SETVAL,nuevo_valor);

Asigna nuevo_valor al semáforo semnum perteneciente al grupo semid

Page 54: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

EJEMPLO PRÁCTICO

Page 55: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Ejemplo (1).

#include <sys/ipc.h>

#include <sys/sem.h>

#define PERMISOS 0644

/* crea_sem: abre o crea un semáforo */

int crea_sem (key_t clave, int valor_inicial){

int semid = semget(clave, 1, IPC_CREAT|PERMISOS);

if ( semid == -1 ) return -1;

/* Da el valor inicial al semáforo */

semctl (semid, 0, SETVAL, valor_inicial );

return semid;

}

Page 56: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

Ejemplo (2). /* abre_sem: Abrir un semáforo que otro proceso ya creó */

int abre_sem (key_t clave){ return semget(clave,1,0); }

/* Operación P */

void sem_P (int semid){

struct sembuf op_P [] = {0, -1, 0};

/* Decrementa semval o bloquea si cero */

semop ( semid, op_P, 1 );

}

/* Operación V */

void sem_V (int semid) {

struct sembuf op_V [] = {0, 1, 0}

/* Incrementa en 1 el semáforo */

semop ( semid, op_V, 1 );

}

Page 57: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

CÓDIGO FUENTEsem_init

findkeynewary

try_semopfreery

sys_semgetsys_semopsys_semctl

Page 58: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sem_init”

void __init sem_init (void)

{

int i;

sem_lock = NULL;

used_sems = used_semids = max_semid = sem_seq = 0;

for (i = 0; i < SEMMNI; i++)

semary[i] = (struct semid_ds *) IPC_UNUSED;

return;

}

Page 59: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sem_init”

void __init sem_init (void)

{

int i;

sem_lock = NULL;

used_sems = used_semids = max_semid = sem_seq = 0;

for (i = 0; i < SEMMNI; i++)

semary[i] = (struct semid_ds *) IPC_UNUSED;

return;

}

Valor especial para semary[id] que nos indica que el semáforo no esta siendo usado

Page 60: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//findkey”

static int findkey (key_t key)

{

int id;

struct semid_ds sma;

for (id = 0; id <= max_semid; id++) {

while ((sma = semary[id]) == IPC_NOID)

interruptible_sleep_on (&sem_lock);

if (sma == IPC_UNUSED)

continue;

if (key == sma->sem_perm.key)

return id;

}

return -1;

}

Page 61: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//findkey”

static int findkey (key_t key)

{

int id;

struct semid_ds sma;

for (id = 0; id <= max_semid; id++) {

while ((sma = semary[id]) == IPC_NOID)

interruptible_sleep_on (&sem_lock);

if (sma == IPC_UNUSED)

continue;

if (key == sma->sem_perm.key)

return id;

}

return -1;

}

Espera hasta que se

termine de destruir.

Page 62: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//findkey”

static int findkey (key_t key)

{

int id;

struct semid_ds sma;

for (id = 0; id <= max_semid; id++) {

while ((sma = semary[id]) == IPC_NOID)

interruptible_sleep_on (&sem_lock);

if (sma == IPC_UNUSED)

continue;

if (key == sma->sem_perm.key)

return id;

}

return -1;

}

Si este semáforo no está siendo usado.

Page 63: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//findkey”

static int findkey (key_t key)

{

int id;

struct semid_ds sma;

for (id = 0; id <= max_semid; id++) {

while ((sma = semary[id]) == IPC_NOID)

interruptible_sleep_on (&sem_lock);

if (sma == IPC_UNUSED)

continue;

if (key == sma->sem_perm.key)

return id;

}

return -1;

}

Si coincide con la clave retornamos

su posición.

Page 64: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//findkey”

static int findkey (key_t key)

{

int id;

struct semid_ds sma;

for (id = 0; id <= max_semid; id++) {

while ((sma = semary[id]) == IPC_NOID)

interruptible_sleep_on (&sem_lock);

if (sma == IPC_UNUSED)

continue;

if (key == sma->sem_perm.key)

return id;

}

return -1;

} Si no está siendo usada devuelve un -1.

Page 65: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (1)

static int newary (key_t key, int nsems, int semflg)

{

int id;

struct semid_ds *sma;

struct ipc_perm *ipcp;

int size;

if (!nsems)

return -EINVAL;

if (used_sems + nsems > SEMMNS)

return -ENOSPC;

for (id = 0; id < SEMMNI; id++)

if (semary[id] == IPC_UNUSED) {

semary[id] = (struct semid_ds *) IPC_NOID;

goto found;

}

return -ENOSPC;

found:

size = sizeof (*sma) + nsems * sizeof (struct sem);

used_sems += nsems;

sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);

Page 66: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (1)

static int newary (key_t key, int nsems, int semflg)

{

int id;

struct semid_ds *sma;

struct ipc_perm *ipcp;

int size;

if (!nsems)

return -EINVAL;

if (used_sems + nsems > SEMMNS)

return -ENOSPC;

for (id = 0; id < SEMMNI; id++)

if (semary[id] == IPC_UNUSED) {

semary[id] = (struct semid_ds *) IPC_NOID;

goto found;

}

return -ENOSPC;

found:

size = sizeof (*sma) + nsems * sizeof (struct sem);

used_sems += nsems;

sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);

Sobrepasaría el numero de semáforos que puede tener el sistema.

Page 67: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (1)

static int newary (key_t key, int nsems, int semflg)

{

int id;

struct semid_ds *sma;

struct ipc_perm *ipcp;

int size;

if (!nsems)

return -EINVAL;

if (used_sems + nsems > SEMMNS)

return -ENOSPC;

for (id = 0; id < SEMMNI; id++)

if (semary[id] == IPC_UNUSED) {

semary[id] = (struct semid_ds *) IPC_NOID;

goto found;

}

return -ENOSPC;

found:

size = sizeof (*sma) + nsems * sizeof (struct sem);

used_sems += nsems;

sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);

Localizamos el primero que este libre.

Page 68: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (1)

static int newary (key_t key, int nsems, int semflg)

{

int id;

struct semid_ds *sma;

struct ipc_perm *ipcp;

int size;

if (!nsems)

return -EINVAL;

if (used_sems + nsems > SEMMNS)

return -ENOSPC;

for (id = 0; id < SEMMNI; id++)

if (semary[id] == IPC_UNUSED) {

semary[id] = (struct semid_ds *) IPC_NOID;

goto found;

}

return -ENOSPC;

found:

size = sizeof (*sma) + nsems * sizeof (struct sem);

used_sems += nsems;

sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);

No se puede crear una tabla nueva.

Page 69: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (1)

static int newary (key_t key, int nsems, int semflg)

{

int id;

struct semid_ds *sma;

struct ipc_perm *ipcp;

int size;

if (!nsems)

return -EINVAL;

if (used_sems + nsems > SEMMNS)

return -ENOSPC;

for (id = 0; id < SEMMNI; id++)

if (semary[id] == IPC_UNUSED) {

semary[id] = (struct semid_ds *) IPC_NOID;

goto found;

}

return -ENOSPC;

found:

size = sizeof (*sma) + nsems * sizeof (struct sem);

used_sems += nsems;

sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);

Calcula cuanto va a tener de tamaño.

Page 70: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (2)if (!sma) {

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_sems -= nsems;

wake_up (&sem_lock);

return -ENOMEM;

}

memset (sma, 0, size);

sma->sem_base = (struct sem *) &sma[1];

ipcp = &sma->sem_perm;

ipcp->mode = (semflg & S_IRWXUGO);

ipcp->key = key;

ipcp->cuid = ipcp->uid = current->euid;

ipcp->gid = ipcp->cgid = current->egid;

sma->sem_perm.seq = sem_seq;

sma->sem_pending_last = &sma->sem_pending;

sma->sem_nsems = nsems;

sma->sem_ctime = CURRENT_TIME;

if (id > max_semid)

max_semid = id;

used_semids++;

semary[id] = sma;

wake_up (&sem_lock);

return (unsigned int) sma->sem_perm.seq * SEMMNI + id;

}

Page 71: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (2)if (!sma) {

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_sems -= nsems;

wake_up (&sem_lock);

return -ENOMEM;

}

memset (sma, 0, size);

sma->sem_base = (struct sem *) &sma[1];

ipcp = &sma->sem_perm;

ipcp->mode = (semflg & S_IRWXUGO);

ipcp->key = key;

ipcp->cuid = ipcp->uid = current->euid;

ipcp->gid = ipcp->cgid = current->egid;

sma->sem_perm.seq = sem_seq;

sma->sem_pending_last = &sma->sem_pending;

sma->sem_nsems = nsems;

sma->sem_ctime = CURRENT_TIME;

if (id > max_semid)

max_semid = id;

used_semids++;

semary[id] = sma;

wake_up (&sem_lock);

return (unsigned int) sma->sem_perm.seq * SEMMNI + id;

}

No hay memoria ¿Pq no se comprueba antes de actualizar variables?

Page 72: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (2)if (!sma) {

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_sems -= nsems;

wake_up (&sem_lock);

return -ENOMEM;

}

memset (sma, 0, size);

sma->sem_base = (struct sem *) &sma[1];

ipcp = &sma->sem_perm;

ipcp->mode = (semflg & S_IRWXUGO);

ipcp->key = key;

ipcp->cuid = ipcp->uid = current->euid;

ipcp->gid = ipcp->cgid = current->egid;

sma->sem_perm.seq = sem_seq;

sma->sem_pending_last = &sma->sem_pending;

sma->sem_nsems = nsems;

sma->sem_ctime = CURRENT_TIME;

if (id > max_semid)

max_semid = id;

used_semids++;

semary[id] = sma;

wake_up (&sem_lock);

return (unsigned int) sma->sem_perm.seq * SEMMNI + id;

}

Puntero al primer semáforo del grupo.

Page 73: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (2)if (!sma) {

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_sems -= nsems;

wake_up (&sem_lock);

return -ENOMEM;

}

memset (sma, 0, size);

sma->sem_base = (struct sem *) &sma[1];

ipcp = &sma->sem_perm;

ipcp->mode = (semflg & S_IRWXUGO);

ipcp->key = key;

ipcp->cuid = ipcp->uid = current->euid;

ipcp->gid = ipcp->cgid = current->egid;

sma->sem_perm.seq = sem_seq;

sma->sem_pending_last = &sma->sem_pending;

sma->sem_nsems = nsems;

sma->sem_ctime = CURRENT_TIME;

if (id > max_semid)

max_semid = id;

used_semids++;

semary[id] = sma;

wake_up (&sem_lock);

return (unsigned int) sma->sem_perm.seq * SEMMNI + id;

}

Fecha del ultimo cambio por semctl.

Page 74: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//newary” (2)if (!sma) {

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_sems -= nsems;

wake_up (&sem_lock);

return -ENOMEM;

}

memset (sma, 0, size);

sma->sem_base = (struct sem *) &sma[1];

ipcp = &sma->sem_perm;

ipcp->mode = (semflg & S_IRWXUGO);

ipcp->key = key;

ipcp->cuid = ipcp->uid = current->euid;

ipcp->gid = ipcp->cgid = current->egid;

sma->sem_perm.seq = sem_seq;

sma->sem_pending_last = &sma->sem_pending;

sma->sem_nsems = nsems;

sma->sem_ctime = CURRENT_TIME;

if (id > max_semid)

max_semid = id;

used_semids++;

semary[id] = sma;

wake_up (&sem_lock);

return (unsigned int) sma->sem_perm.seq * SEMMNI + id;

}

Fecha del ultimo cambio por semctl.

Page 75: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//try_semop” (1)static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,

int nsops, struct sem_undo *un, int pid, int do_undo)

{

int result, sem_op;

struct sembuf *sop;

struct sem * curr;

for (sop = sops; sop < sops + nsops; sop++) {

curr = sma->sem_base + sop->sem_num;

sem_op = sop->sem_op;

if (!sem_op && curr->semval)

goto would_block;

curr->sempid = (curr->sempid << 16) | pid;

curr->semval += sem_op;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] -= sem_op;

if (curr->semval < 0)

goto would_block;

if (curr->semval > SEMVMX)

goto out_of_range;

}

Page 76: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//try_semop” (1)static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,

int nsops, struct sem_undo *un, int pid, int do_undo)

{

int result, sem_op;

struct sembuf *sop;

struct sem * curr;

for (sop = sops; sop < sops + nsops; sop++) {

curr = sma->sem_base + sop->sem_num;

sem_op = sop->sem_op;

if (!sem_op && curr->semval)

goto would_block;

curr->sempid = (curr->sempid << 16) | pid;

curr->semval += sem_op;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] -= sem_op;

if (curr->semval < 0)

goto would_block;

if (curr->semval > SEMVMX)

goto out_of_range;

}

Se inicializa sop y se itera tantas veces nsops

Page 77: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//try_semop” (1)static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,

int nsops, struct sem_undo *un, int pid, int do_undo)

{

int result, sem_op;

struct sembuf *sop;

struct sem * curr;

for (sop = sops; sop < sops + nsops; sop++) {

curr = sma->sem_base + sop->sem_num;

sem_op = sop->sem_op;

if (!sem_op && curr->semval)

goto would_block;

curr->sempid = (curr->sempid << 16) | pid;

curr->semval += sem_op;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] -= sem_op;

if (curr->semval < 0)

goto would_block;

if (curr->semval > SEMVMX)

goto out_of_range;

}

sem_op == 0 quiere esperar a que curr->semval llegue a cero por lo que si no éste ultimo no es cero

tendrá que bloquearse.

Page 78: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//try_semop” (1)static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,

int nsops, struct sem_undo *un, int pid, int do_undo)

{

int result, sem_op;

struct sembuf *sop;

struct sem * curr;

for (sop = sops; sop < sops + nsops; sop++) {

curr = sma->sem_base + sop->sem_num;

sem_op = sop->sem_op;

if (!sem_op && curr->semval)

goto would_block;

curr->sempid = (curr->sempid << 16) | pid;

curr->semval += sem_op;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] -= sem_op;

if (curr->semval < 0)

goto would_block;

if (curr->semval > SEMVMX)

goto out_of_range;

}

Si SEM_UNDO está seleccionada significa que la operación debe ser deshecha cuando el procesotermine por lo que se actualiza dicha estructura

Page 79: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c// try_semop” (2)if (do_undo){

sop--;

result = 0;

goto undo;

}

sma->sem_otime = CURRENT_TIME; /* Valor de tocado */

return 0;

out_of_range:

result = -ERANGE;

goto undo;

would_block:

if (sop->sem_flg & IPC_NOWAIT)

result = -EAGAIN;

else

result = 1;

undo:

while (sop >= sops) {

curr = sma->sem_base + sop->sem_num;

curr->semval -= sop->sem_op;

curr->sempid >>= 16;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] += sop->sem_op;

sop--;

}

return result;

}

Page 80: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c// try_semop” (2)if (do_undo){

sop--;

result = 0;

goto undo;

}

sma->sem_otime = CURRENT_TIME; /* Valor de tocado */

return 0;

out_of_range:

result = -ERANGE;

goto undo;

would_block:

if (sop->sem_flg & IPC_NOWAIT)

result = -EAGAIN;

else

result = 1;

undo:

while (sop >= sops) {

curr = sma->sem_base + sop->sem_num;

curr->semval -= sop->sem_op;

curr->sempid >>= 16;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] += sop->sem_op;

sop--;

}

return result;

}

El bucle terminó por lo que todas las operaciones fueron exitosas. Si el proceso llamante quiere saber si son exitosas pero no desarrollarlas

entonces las operaciones son deshechas.

Page 81: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c// try_semop” (2)if (do_undo){

sop--;

result = 0;

goto undo;

}

sma->sem_otime = CURRENT_TIME; /* Valor de tocado */

return 0;

out_of_range:

result = -ERANGE;

goto undo;

would_block:

if (sop->sem_flg & IPC_NOWAIT)

result = -EAGAIN;

else

result = 1;

undo:

while (sop >= sops) {

curr = sma->sem_base + sop->sem_num;

curr->semval -= sop->sem_op;

curr->sempid >>= 16;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] += sop->sem_op;

sop--;

}

return result;

}

Ocurre cuando una operación modificó el valor de semval

por encima de su valor máximo

Page 82: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c// try_semop” (2)if (do_undo){

sop--;

result = 0;

goto undo;

}

sma->sem_otime = CURRENT_TIME; /* Valor de tocado */

return 0;

out_of_range:

result = -ERANGE;

goto undo;

would_block:

if (sop->sem_flg & IPC_NOWAIT)

result = -EAGAIN;

else

result = 1;

undo:

while (sop >= sops) {

curr = sma->sem_base + sop->sem_num;

curr->semval -= sop->sem_op;

curr->sempid >>= 16;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] += sop->sem_op;

sop--;

}

return result;

}

El proceso debe esperar en un semáforo, o bien a que llegue a cero o bien porque lo requiere inmediatamente,

saliendo con un error en este ultimo caso.

Page 83: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c// try_semop” (2)if (do_undo){

sop--;

result = 0;

goto undo;

}

sma->sem_otime = CURRENT_TIME; /* Valor de tocado */

return 0;

out_of_range:

result = -ERANGE;

goto undo;

would_block:

if (sop->sem_flg & IPC_NOWAIT)

result = -EAGAIN;

else

result = 1;

undo:

while (sop >= sops) {

curr = sma->sem_base + sop->sem_num;

curr->semval -= sop->sem_op;

curr->sempid >>= 16;

if (sop->sem_flg & SEM_UNDO)

un->semadj[sop->sem_num] += sop->sem_op;

sop--;

}

return result;

}

Deshace todo el trabajo hecho en el primer bucle.

Page 84: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//freery”static void freeary (int id)

{

struct semid_ds *sma = semary[id];

struct sem_undo *un;

struct sem_queue *q;

sma->sem_perm.seq++;

sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI);

used_sems -= sma->sem_nsems;

if (id == max_semid)

while (max_semid &&

(semary[--max_semid] == IPC_UNUSED));

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_semids--;

for (un = sma->undo; un; un = un->id_next)

un->semid = -1;

for (q = sma->sem_pending; q; q = q->next) {

q->status = -EIDRM;

q->prev = NULL;

wake_up_interruptible(&q->sleeper);

}

kfree(sma);

}

Page 85: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//freery”static void freeary (int id)

{

struct semid_ds *sma = semary[id];

struct sem_undo *un;

struct sem_queue *q;

sma->sem_perm.seq++;

sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI);

used_sems -= sma->sem_nsems;

if (id == max_semid)

while (max_semid &&

(semary[--max_semid] == IPC_UNUSED));

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_semids--;

for (un = sma->undo; un; un = un->id_next)

un->semid = -1;

for (q = sma->sem_pending; q; q = q->next) {

q->status = -EIDRM;

q->prev = NULL;

wake_up_interruptible(&q->sleeper);

}

kfree(sma);

}

Invalida este grupo de semáforos.

Page 86: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//freery”static void freeary (int id)

{

struct semid_ds *sma = semary[id];

struct sem_undo *un;

struct sem_queue *q;

sma->sem_perm.seq++;

sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI);

used_sems -= sma->sem_nsems;

if (id == max_semid)

while (max_semid &&

(semary[--max_semid] == IPC_UNUSED));

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_semids--;

for (un = sma->undo; un; un = un->id_next)

un->semid = -1;

for (q = sma->sem_pending; q; q = q->next) {

q->status = -EIDRM;

q->prev = NULL;

wake_up_interruptible(&q->sleeper);

}

kfree(sma);

}

Incrementa pero evita desbordamiento.

Page 87: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//freery”static void freeary (int id)

{

struct semid_ds *sma = semary[id];

struct sem_undo *un;

struct sem_queue *q;

sma->sem_perm.seq++;

sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI);

used_sems -= sma->sem_nsems;

if (id == max_semid)

while (max_semid &&

(semary[--max_semid] == IPC_UNUSED));

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_semids--;

for (un = sma->undo; un; un = un->id_next)

un->semid = -1;

for (q = sma->sem_pending; q; q = q->next) {

q->status = -EIDRM;

q->prev = NULL;

wake_up_interruptible(&q->sleeper);

}

kfree(sma);

}

Indica que está libre.

Page 88: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//freery”static void freeary (int id)

{

struct semid_ds *sma = semary[id];

struct sem_undo *un;

struct sem_queue *q;

sma->sem_perm.seq++;

sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI);

used_sems -= sma->sem_nsems;

if (id == max_semid)

while (max_semid &&

(semary[--max_semid] == IPC_UNUSED));

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_semids--;

for (un = sma->undo; un; un = un->id_next)

un->semid = -1;

for (q = sma->sem_pending; q; q = q->next) {

q->status = -EIDRM;

q->prev = NULL;

wake_up_interruptible(&q->sleeper);

}

kfree(sma);

}

Invalida la estructura undo asociada a este.

Page 89: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//freery”static void freeary (int id)

{

struct semid_ds *sma = semary[id];

struct sem_undo *un;

struct sem_queue *q;

sma->sem_perm.seq++;

sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI);

used_sems -= sma->sem_nsems;

if (id == max_semid)

while (max_semid &&

(semary[--max_semid] == IPC_UNUSED));

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_semids--;

for (un = sma->undo; un; un = un->id_next)

un->semid = -1;

for (q = sma->sem_pending; q; q = q->next) {

q->status = -EIDRM;

q->prev = NULL;

wake_up_interruptible(&q->sleeper);

}

kfree(sma);

}

Despierta todos los procesos que están esperando

indicando además error EIDRM.

Page 90: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//freery”static void freeary (int id)

{

struct semid_ds *sma = semary[id];

struct sem_undo *un;

struct sem_queue *q;

sma->sem_perm.seq++;

sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI);

used_sems -= sma->sem_nsems;

if (id == max_semid)

while (max_semid &&

(semary[--max_semid] == IPC_UNUSED));

semary[id] = (struct semid_ds *) IPC_UNUSED;

used_semids--;

for (un = sma->undo; un; un = un->id_next)

un->semid = -1;

for (q = sma->sem_pending; q; q = q->next) {

q->status = -EIDRM;

q->prev = NULL;

wake_up_interruptible(&q->sleeper);

}

kfree(sma);

} Libera la memoria asociada.

Page 91: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

asmlinkage int sys_semget (key_t key, int nsems, int semflg)

{

int id, err = -EINVAL;

struct semid_ds *sma;

lock_kernel();

if (nsems < 0 || nsems > SEMMSL)

goto out;

if (key == IPC_PRIVATE) {

err = newary (key, nsems, semflg);

} else if ((id = findkey (key)) == -1) {

if (!(semflg & IPC_CREAT))

err = -ENOENT;

else

err = newary (key, nsems, semflg);

}

“ipc/sem.c//sys_semget” (1)

Page 92: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (1)

asmlinkage int sys_semget (key_t key, int nsems, int semflg)

{

int id, err = -EINVAL;

struct semid_ds *sma;

lock_kernel();

if (nsems < 0 || nsems > SEMMSL)

goto out;

if (key == IPC_PRIVATE) {

err = newary (key, nsems, semflg);

} else if ((id = findkey (key)) == -1) {

if (!(semflg & IPC_CREAT))

err = -ENOENT;

else

err = newary (key, nsems, semflg);

}

SEMMSL es el nº máximo de semáforos por grupo.

Page 93: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (1)

asmlinkage int sys_semget (key_t key, int nsems, int semflg)

{

int id, err = -EINVAL;

struct semid_ds *sma;

lock_kernel();

if (nsems < 0 || nsems > SEMMSL)

goto out;

if (key == IPC_PRIVATE) {

err = newary (key, nsems, semflg);

} else if ((id = findkey (key)) == -1) {

if (!(semflg & IPC_CREAT))

err = -ENOENT;

else

err = newary (key, nsems, semflg);

}

Se ocupa la primera entrada que se encuentre libre y ninguna llamada semget podrá

devolverla hasta que lo liberemos.

Page 94: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (1)

asmlinkage int sys_semget (key_t key, int nsems, int semflg)

{

int id, err = -EINVAL;

struct semid_ds *sma;

lock_kernel();

if (nsems < 0 || nsems > SEMMSL)

goto out;

if (key == IPC_PRIVATE) {

err = newary (key, nsems, semflg);

} else if ((id = findkey (key)) == -1) {

if (!(semflg & IPC_CREAT))

err = -ENOENT;

else

err = newary (key, nsems, semflg);

}

Si key tiene un valor no especial, entonces se comprueba que no existe un

grupo de semaforos con esa clave.

Page 95: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (1)

asmlinkage int sys_semget (key_t key, int nsems, int semflg)

{

int id, err = -EINVAL;

struct semid_ds *sma;

lock_kernel();

if (nsems < 0 || nsems > SEMMSL)

goto out;

if (key == IPC_PRIVATE) {

err = newary (key, nsems, semflg);

} else if ((id = findkey (key)) == -1) {

if (!(semflg & IPC_CREAT))

err = -ENOENT;

else

err = newary (key, nsems, semflg);

}

Se creará si otro proceso no la ha creado ya.

Page 96: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (2)

else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {

err = -EEXIST;

} else {

sma = semary[id];

if (nsems > sma->sem_nsems)

err = -EINVAL;

else if (ipcperms(&sma->sem_perm, semflg))

err = -EACCES;

else

err = (int) sma->sem_perm.seq * SEMMNI + id;

}

out:

unlock_kernel();

return err;

}

Page 97: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (2)

else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {

err = -EEXIST;

} else {

sma = semary[id];

if (nsems > sma->sem_nsems)

err = -EINVAL;

else if (ipcperms(&sma->sem_perm, semflg))

err = -EACCES;

else

err = (int) sma->sem_perm.seq * SEMMNI + id;

}

out:

unlock_kernel();

return err;

}

La llamada falla por que el grupo de semáforos ya fue creado.

Page 98: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (2)

else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {

err = -EEXIST;

} else {

sma = semary[id];

if (nsems > sma->sem_nsems)

err = -EINVAL;

else if (ipcperms(&sma->sem_perm, semflg))

err = -EACCES;

else

err = (int) sma->sem_perm.seq * SEMMNI + id;

}

out:

unlock_kernel();

return err;

}

Se coge el que devuelve find.

Page 99: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (2)

else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {

err = -EEXIST;

} else {

sma = semary[id];

if (nsems > sma->sem_nsems)

err = -EINVAL;

else if (ipcperms(&sma->sem_perm, semflg))

err = -EACCES;

else

err = (int) sma->sem_perm.seq * SEMMNI + id;

}

out:

unlock_kernel();

return err;

}

El nº de semáforos del grupo es > que el del existente.

Page 100: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (2)

else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {

err = -EEXIST;

} else {

sma = semary[id];

if (nsems > sma->sem_nsems)

err = -EINVAL;

else if (ipcperms(&sma->sem_perm, semflg))

err = -EACCES;

else

err = (int) sma->sem_perm.seq * SEMMNI + id;

}

out:

unlock_kernel();

return err;

}

Se comprueba que tiene permiso de acceso.

Page 101: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semget” (2)

else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {

err = -EEXIST;

} else {

sma = semary[id];

if (nsems > sma->sem_nsems)

err = -EINVAL;

else if (ipcperms(&sma->sem_perm, semflg))

err = -EACCES;

else

err = (int) sma->sem_perm.seq * SEMMNI + id;

}

out:

unlock_kernel();

return err;

}

Se comprueba que tiene permiso de acceso.

Page 102: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (1)

asmlinkage int sys_semop(int semid, struct sembuf *tsops, unsigned nsops)

{

int id, size, error = -EINVAL;

struct semid_ds *sma;

struct sembuf sops[SEMOPM], *sop;

struct sem_undo *un;

int undos = 0, decrease = 0, alter = 0;

struct sem_queue queue;

lock_kernel();

if (nsops < 1 || semid < 0)

goto out;

error = -E2BIG;

if (nsops > SEMOPM)

goto out;

error = -EFAULT;

if(copy_from_user(sops, tsops, nsops * sizeof(*tsops)))

goto out;

id = (unsigned int) semid % SEMMNI;

error = -EINVAL;

if((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)

goto out;

Page 103: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (1)

asmlinkage int sys_semop(int semid, struct sembuf *tsops, unsigned nsops)

{

int id, size, error = -EINVAL;

struct semid_ds *sma;

struct sembuf sops[SEMOPM], *sop;

struct sem_undo *un;

int undos = 0, decrease = 0, alter = 0;

struct sem_queue queue;

lock_kernel();

if (nsops < 1 || semid < 0)

goto out;

error = -E2BIG;

if (nsops > SEMOPM)

goto out;

error = -EFAULT;

if(copy_from_user(sops, tsops, nsops * sizeof(*tsops)))

goto out;

id = (unsigned int) semid % SEMMNI;

error = -EINVAL;

if((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)

goto out;

Comprueba que los argumentos son validos.

Page 104: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (1)

asmlinkage int sys_semop(int semid, struct sembuf *tsops,

unsigned nsops)

{

int id, size, error = -EINVAL;

struct semid_ds *sma;

struct sembuf sops[SEMOPM], *sop;

struct sem_undo *un;

int undos = 0, decrease = 0, alter = 0;

struct sem_queue queue;

lock_kernel();

if (nsops < 1 || semid < 0)

goto out;

error = -E2BIG;

if (nsops > SEMOPM)

goto out;

error = -EFAULT;

if(copy_from_user(sops, tsops, nsops * sizeof(*tsops)))

goto out;

id = (unsigned int) semid % SEMMNI;

error = -EINVAL;

if((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)

goto out;

nsop no debe ser superior a SEMOPM, es decir el nº máximo de operaciones permitidas

Page 105: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (1)

asmlinkage int sys_semop(int semid, struct sembuf *tsops,

unsigned nsops)

{

int id, size, error = -EINVAL;

struct semid_ds *sma;

struct sembuf sops[SEMOPM], *sop;

struct sem_undo *un;

int undos = 0, decrease = 0, alter = 0;

struct sem_queue queue;

lock_kernel();

if (nsops < 1 || semid < 0)

goto out;

error = -E2BIG;

if (nsops > SEMOPM)

goto out;

error = -EFAULT;

if(copy_from_user(sops, tsops, nsops * sizeof(*tsops)))

goto out;

id = (unsigned int) semid % SEMMNI;

error = -EINVAL;

if((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)

goto out;

Copia la descripción de la operación requerida desde el espacio de usuario a un búfer temporal

Page 106: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (1)

asmlinkage int sys_semop(int semid, struct sembuf *tsops,

unsigned nsops)

{

int id, size, error = -EINVAL;

struct semid_ds *sma;

struct sembuf sops[SEMOPM], *sop;

struct sem_undo *un;

int undos = 0, decrease = 0, alter = 0;

struct sem_queue queue;

lock_kernel();

if (nsops < 1 || semid < 0)

goto out;

error = -E2BIG;

if (nsops > SEMOPM)

goto out;

error = -EFAULT;

if(copy_from_user(sops, tsops, nsops * sizeof(*tsops)))

goto out;

id = (unsigned int) semid % SEMMNI;

error = -EINVAL;

if((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)

goto out;

Índice en el vector y comprueba que está en uso.

Page 107: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (1)

asmlinkage int sys_semop(int semid, struct sembuf *tsops,

unsigned nsops)

{

int id, size, error = -EINVAL;

struct semid_ds *sma;

struct sembuf sops[SEMOPM], *sop;

struct sem_undo *un;

int undos = 0, decrease = 0, alter = 0;

struct sem_queue queue;

lock_kernel();

if (nsops < 1 || semid < 0)

goto out;

error = -E2BIG;

if (nsops > SEMOPM)

goto out;

error = -EFAULT;

if(copy_from_user(sops, tsops, nsops * sizeof(*tsops)))

goto out;

id = (unsigned int) semid % SEMMNI;

error = -EINVAL;

if((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)

goto out;

Se asegura que la entrada exista en el indicado array de posiciones.

Page 108: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (2)

error = -EIDRM;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

error = -EFBIG;

for (sop = sops; sop < sops + nsops; sop++) {

if (sop->sem_num >= sma->sem_nsems)

goto out;

if (sop->sem_flg & SEM_UNDO)

undos++;

if (sop->sem_op < 0)

decrease = 1;

if (sop->sem_op > 0)

alter = 1;

}

alter |= decrease;

error = -EACCES;

if(ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) goto out;

Page 109: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (2)

error = -EIDRM;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

error = -EFBIG;

for (sop = sops; sop < sops + nsops; sop++) {

if (sop->sem_num >= sma->sem_nsems)

goto out;

if (sop->sem_flg & SEM_UNDO)

undos++;

if (sop->sem_op < 0)

decrease = 1;

if (sop->sem_op > 0)

alter = 1;

}

alter |= decrease;

error = -EACCES;

if(ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) goto out;

Se asegura que tiene permiso sobre el semáforo.

Page 110: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (2)

error = -EIDRM;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

error = -EFBIG;

for (sop = sops; sop < sops + nsops; sop++) {

if (sop->sem_num >= sma->sem_nsems)

goto out;

if (sop->sem_flg & SEM_UNDO)

undos++;

if (sop->sem_op < 0)

decrease = 1;

if (sop->sem_op > 0)

alter = 1;

}

alter |= decrease;

error = -EACCES;

if(ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) goto out;

Cuenta el nº de operaciones cuyo sem_flag

está seleccionado.

Page 111: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (2)

error = -EIDRM;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

error = -EFBIG;

for (sop = sops; sop < sops + nsops; sop++) {

if (sop->sem_num >= sma->sem_nsems)

goto out;

if (sop->sem_flg & SEM_UNDO)

undos++;

if (sop->sem_op < 0)

decrease = 1;

if (sop->sem_op > 0)

alter = 1;

}

alter |= decrease;

error = -EACCES;

if(ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) goto out;

Bucle para todas las operaciones donde primero chequea que el número de semáforo no esta fuera de rango, rechazandoen caso contrario, dando un error de EFBIG en lugar de EINVAL

que es lo que en teoría debería ser.

Page 112: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (2)

error = -EIDRM;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

error = -EFBIG;

for (sop = sops; sop < sops + nsops; sop++) {

if (sop->sem_num >= sma->sem_nsems)

goto out;

if (sop->sem_flg & SEM_UNDO)

undos++;

if (sop->sem_op < 0)

decrease = 1;

if (sop->sem_op > 0)

alter = 1;

}

alter |= decrease;

error = -EACCES;

if(ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) goto out;

Decrease indica si alguna operación decrementará el valordel semáforo y alter si alguna lo incrementará.

Page 113: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (3)

if (undos) {

for (un = current->semundo; un; un = un->proc_next)

if (un->semid == semid)

break;

if (!un) {

size = sizeof(struct sem_undo) +

sizeof(short) * sma->sem_nsems;

un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);

if (!un) {

error = -ENOMEM;

goto out;

}

memset(un, 0, size);

un->semadj = (short *) &un[1];

un->semid = semid;

un->proc_next = current->semundo;

current->semundo = un;

un->id_next = sma->undo;

sma->undo = un;

}

Page 114: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (3)

if (undos) {

for (un = current->semundo; un; un = un->proc_next)

if (un->semid == semid)

break;

if (!un) {

size = sizeof(struct sem_undo) +

sizeof(short) * sma->sem_nsems;

un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);

if (!un) {

error = -ENOMEM;

goto out;

}

memset(un, 0, size);

un->semadj = (short *) &un[1];

un->semid = semid;

un->proc_next = current->semundo;

current->semundo = un;

un->id_next = sma->undo;

sma->undo = un;

}

Bucle encuentra el conjunto actual de operaciones dejando un puntero.

Page 115: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (3)

if (undos) {

for (un = current->semundo; un; un = un->proc_next)

if (un->semid == semid)

break;

if (!un) {

size = sizeof(struct sem_undo) +

sizeof(short) * sma->sem_nsems;

un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);

if (!un) {

error = -ENOMEM;

goto out;

}

memset(un, 0, size);

un->semadj = (short *) &un[1];

un->semid = semid;

un->proc_next = current->semundo;

current->semundo = un;

un->id_next = sma->undo;

sma->undo = un;

}

Aun no tiene listo un conjunto para este grupo de

semáforos, entonces uno nuevo es asignado

Page 116: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (3)

if (undos) {

for (un = current->semundo; un; un = un->proc_next)

if (un->semid == semid)

break;

if (!un) {

size = sizeof(struct sem_undo) +

sizeof(short) * sma->sem_nsems;

un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);

if (!un) {

error = -ENOMEM;

goto out;

}

memset(un, 0, size);

un->semadj = (short *) &un[1];

un->semid = semid;

un->proc_next = current->semundo;

current->semundo = un;

un->id_next = sma->undo;

sma->undo = un;

}

Si no encuentra ninguno, sale.

Page 117: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (3)

if (undos) {

for (un = current->semundo; un; un = un->proc_next)

if (un->semid == semid)

break;

if (!un) {

size = sizeof(struct sem_undo) +

sizeof(short) * sma->sem_nsems;

un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);

if (!un) {

error = -ENOMEM;

goto out;

}

memset(un, 0, size);

un->semadj = (short *) &un[1];

un->semid = semid;

un->proc_next = current->semundo;

current->semundo = un;

un->id_next = sma->undo;

sma->undo = un;

}

En caso de encontrar uno, indica que es el actual, y que el actual es

el siguiente.

Page 118: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (4)

} else un = NULL;

error = try_atomic_semop(sma, sops, nsops, un, current->pid, 0);

if (error <= 0)

goto update;

queue.sma = sma;

queue.sops = sops;

queue.nsops = nsops;

queue.undo = un;

queue.pid = current->pid;

queue.alter = decrease;

current->semsleeping = &queue;

if (alter)

append_to_queue(sma ,&queue);

else

prepend_to_queue(sma ,&queue);

Page 119: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (4)

} else un = NULL;

error = try_atomic_semop(sma, sops, nsops, un, current->pid, 0);

if (error <= 0)

goto update;

queue.sma = sma;

queue.sops = sops;

queue.nsops = nsops;

queue.undo = un;

queue.pid = current->pid;

queue.alter = decrease;

current->semsleeping = &queue;

if (alter)

append_to_queue(sma ,&queue);

else

prepend_to_queue(sma ,&queue);

No hay ningún conjunto de operaciones, entonces se pone a nulo.

Page 120: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (4)

} else un = NULL;

error = try_atomic_semop(sma, sops, nsops, un, current->pid, 0);

if (error <= 0)

goto update;

queue.sma = sma;

queue.sops = sops;

queue.nsops = nsops;

queue.undo = un;

queue.pid = current->pid;

queue.alter = decrease;

current->semsleeping = &queue;

if (alter)

append_to_queue(sma ,&queue);

else

prepend_to_queue(sma ,&queue);

Llama a try_atomic_semop para que desarrolle todas las operaciones en un solo paso.

Page 121: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (4)

} else un = NULL;

error = try_atomic_semop(sma, sops, nsops, un, current->pid, 0);

if (error <= 0)

goto update;

queue.sma = sma;

queue.sops = sops;

queue.nsops = nsops;

queue.undo = un;

queue.pid = current->pid;

queue.alter = decrease;

current->semsleeping = &queue;

if (alter)

append_to_queue(sma ,&queue);

else

prepend_to_queue(sma ,&queue);

Si concluye con éxito devuelve un cero y en caso contrario un numero negativo.

Page 122: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (4)

} else un = NULL;

error = try_atomic_semop(sma, sops, nsops, un, current->pid, 0);

if (error <= 0)

goto update;

queue.sma = sma;

queue.sops = sops;

queue.nsops = nsops;

queue.undo = un;

queue.pid = current->pid;

queue.alter = decrease;

current->semsleeping = &queue;

if (alter)

append_to_queue(sma ,&queue);

else

prepend_to_queue(sma ,&queue);

Si valor positivo, entonces las operaciones no pudieron se realizadas, pero el proceso quiere esperer y

tratarlo después por lo que se encola

rellenando para ello una sem_queued

Page 123: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

} else un = NULL;

error = try_atomic_semop(sma, sops, nsops, un, current->pid, 0);

if (error <= 0)

goto update;

queue.sma = sma;

queue.sops = sops;

queue.nsops = nsops;

queue.undo = un;

queue.pid = current->pid;

queue.alter = decrease;

current->semsleeping = &queue;

if (alter)

append_to_queue(sma ,&queue);

else

prepend_to_queue(sma ,&queue);

Los nodos que representan operaciones que modificarán el semáforo son situados al final de la cola, y los nodos que están esperando

a que el valor del semáforo llegue a cero son puestos al principio.

“ipc/sem.c//sys_semop” (4)

Page 124: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (5) for (;;) { queue.status = -EINTR;

queue.sleeper = NULL;

interruptible_sleep_on(&queue.sleeper);

if (queue.status == 1){

error = try_atomic_semop (sma, sops, nsops, un, current->pid,0);

if (error <= 0)

break;

} else {

error = queue.status;;

if (queue.prev) /* got Interrupt */

break;

current->semsleeping = NULL;

goto out;

}

}

current->semsleeping = NULL;

remove_from_queue(sma,&queue);

update:

if (alter)

update_queue (sma);

out:

unlock_kernel();

return error;

}

Page 125: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (5) for (;;) { queue.status = -EINTR;

queue.sleeper = NULL;

interruptible_sleep_on(&queue.sleeper);

if (queue.status == 1){

error = try_atomic_semop (sma, sops, nsops, un, current->pid,0);

if (error <= 0)

break;

} else {

error = queue.status;;

if (queue.prev) /* got Interrupt */

break;

current->semsleeping = NULL;

goto out;

}

}

current->semsleeping = NULL;

remove_from_queue(sma,&queue);

update:

if (alter)

update_queue (sma);

out:

unlock_kernel();

return error;

}

Empieza un bucle que repetidamente intenta desarrollar las operaciones, saliendo sólo cuando la requerida operación se haya desarrollado con

éxito o cuando se produzca un error.

Page 126: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (5) for (;;) { queue.status = -EINTR;

queue.sleeper = NULL;

interruptible_sleep_on(&queue.sleeper);

if (queue.status == 1){

error = try_atomic_semop (sma, sops, nsops, un, current->pid,0);

if (error <= 0)

break;

} else {

error = queue.status;;

if (queue.prev) /* got Interrupt */

break;

current->semsleeping = NULL;

goto out;

}

}

current->semsleeping = NULL;

remove_from_queue(sma,&queue);

update:

if (alter)

update_queue (sma);

out:

unlock_kernel();

return error;

}

Duerme hasta lo despierte un signal o haya algún momento para intentarlo de nuevo.

Page 127: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (5) for (;;) { queue.status = -EINTR;

queue.sleeper = NULL;

interruptible_sleep_on(&queue.sleeper);

if (queue.status == 1){

error = try_atomic_semop (sma, sops, nsops, un, current->pid,0);

if (error <= 0)

break;

} else {

error = queue.status;;

if (queue.prev) /* got Interrupt */

break;

current->semsleeping = NULL;

goto out;

}

}

current->semsleeping = NULL;

remove_from_queue(sma,&queue);

update:

if (alter)

update_queue (sma);

out:

unlock_kernel();

return error;

}

Si el proceso es despertado ahora tiene una oportunidad

para intentarlo de nuevo.

Page 128: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (5) for (;;) { queue.status = -EINTR;

queue.sleeper = NULL;

interruptible_sleep_on(&queue.sleeper);

if (queue.status == 1){

error = try_atomic_semop (sma, sops, nsops, un, current->pid,0);

if (error <= 0)

break;

} else {

error = queue.status;;

if (queue.prev) /* got Interrupt */

break;

current->semsleeping = NULL;

goto out;

}

}

current->semsleeping = NULL;

remove_from_queue(sma,&queue);

update:

if (alter)

update_queue (sma);

out:

unlock_kernel();

return error;

}

Quita al proceso de la cola de procesos que están.

Page 129: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (5) for (;;) { queue.status = -EINTR;

queue.sleeper = NULL;

interruptible_sleep_on(&queue.sleeper);

if (queue.status == 1){

error = try_atomic_semop (sma, sops, nsops, un, current->pid,0);

if (error <= 0)

break;

} else {

error = queue.status;;

if (queue.prev) /* got Interrupt */

break;

current->semsleeping = NULL;

goto out;

}

}

current->semsleeping = NULL;

remove_from_queue(sma,&queue);

update:

if (alter)

update_queue (sma);

out:

unlock_kernel();

return error;

}

Si el conjunto de operaciones alteró la cola es posible que haya modificado las condiciones de otros proceso que estuvieran

esperando, por lo que intenta despertar alguna proceso.

Page 130: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semop” (5) for (;;) { queue.status = -EINTR;

queue.sleeper = NULL;

interruptible_sleep_on(&queue.sleeper);

if (queue.status == 1){

error = try_atomic_semop (sma, sops, nsops, un, current->pid,0);

if (error <= 0)

break;

} else {

error = queue.status;;

if (queue.prev) /* got Interrupt */

break;

current->semsleeping = NULL;

goto out;

}

}

current->semsleeping = NULL;

remove_from_queue(sma,&queue);

update:

if (alter)

update_queue (sma);

out:

unlock_kernel();

return error;

}

Si el conjunto de operaciones alteró la cola es posible que haya modificado las condiciones de otros proceso que estuvieran

esperando, por lo que intenta despertar alguna proceso.

Page 131: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (1)

asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg)

{

struct semid_ds *buf = NULL;

struct semid_ds tbuf;

int i, id, val = 0;

struct semid_ds *sma;

struct ipc_perm *ipcp;

struct sem *curr = NULL;

struct sem_undo *un;

unsigned int nsems;

ushort *array = NULL;

ushort sem_io[SEMMSL];

int err = -EINVAL;

lock_kernel();

if (semid < 0 || semnum < 0 || cmd < 0)

goto out;

switch (cmd) {

case IPC_INFO:

Page 132: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (1)

asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg)

{

struct semid_ds *buf = NULL;

struct semid_ds tbuf;

int i, id, val = 0;

struct semid_ds *sma;

struct ipc_perm *ipcp;

struct sem *curr = NULL;

struct sem_undo *un;

unsigned int nsems;

ushort *array = NULL;

ushort sem_io[SEMMSL];

int err = -EINVAL;

lock_kernel();

if (semid < 0 || semnum < 0 || cmd < 0)

goto out;

switch (cmd) {

case IPC_INFO:

Si hay algún error de parámetro de entrada se sale.

Page 133: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (2)

case SEM_INFO:

{

struct seminfo seminfo, *tmp = arg.__buf;

seminfo.semmni = SEMMNI;

seminfo.semmns = SEMMNS;

seminfo.semmsl = SEMMSL;

seminfo.semopm = SEMOPM;

seminfo.semvmx = SEMVMX;

seminfo.semmnu = SEMMNU;

seminfo.semmap = SEMMAP;

seminfo.semume = SEMUME;

seminfo.semusz = SEMUSZ;

seminfo.semaem = SEMAEM;

if (cmd == SEM_INFO) {

seminfo.semusz = used_semids;

seminfo.semaem = used_sems;

}

err = -EFAULT;

if (copy_to_user (tmp, &seminfo, sizeof(struct seminfo)))

goto out;

err = max_semid;

goto out;

}

Page 134: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (2)

case SEM_INFO:

{

struct seminfo seminfo, *tmp = arg.__buf;

seminfo.semmni = SEMMNI;

seminfo.semmns = SEMMNS;

seminfo.semmsl = SEMMSL;

seminfo.semopm = SEMOPM;

seminfo.semvmx = SEMVMX;

seminfo.semmnu = SEMMNU;

seminfo.semmap = SEMMAP;

seminfo.semume = SEMUME;

seminfo.semusz = SEMUSZ;

seminfo.semaem = SEMAEM;

if (cmd == SEM_INFO) {

seminfo.semusz = used_semids;

seminfo.semaem = used_sems;

}

err = -EFAULT;

if (copy_to_user (tmp, &seminfo, sizeof(struct seminfo)))

goto out;

err = max_semid;

goto out;

}

Información actual de los semáforos.

Page 135: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (2)

case SEM_INFO:

{

struct seminfo seminfo, *tmp = arg.__buf;

seminfo.semmni = SEMMNI;

seminfo.semmns = SEMMNS;

seminfo.semmsl = SEMMSL;

seminfo.semopm = SEMOPM;

seminfo.semvmx = SEMVMX;

seminfo.semmnu = SEMMNU;

seminfo.semmap = SEMMAP;

seminfo.semume = SEMUME;

seminfo.semusz = SEMUSZ;

seminfo.semaem = SEMAEM;

if (cmd == SEM_INFO) {

seminfo.semusz = used_semids;

seminfo.semaem = used_sems;

}

err = -EFAULT;

if (copy_to_user (tmp, &seminfo, sizeof(struct seminfo)))

goto out;

err = max_semid;

goto out;

}

Copia la estructura recién copiada en la memoria de usuario.

Page 136: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (3)

case SEM_STAT: buf = arg.buf;

err = -EINVAL;

if (semid > max_semid)

goto out;

sma = semary[semid];

if (sma == IPC_UNUSED || sma == IPC_NOID)

goto out;

err = -EACCES;

if (ipcperms (&sma->sem_perm, S_IRUGO))

goto out;

id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

err = -EFAULT;

if (copy_to_user (buf, &tbuf, sizeof(*buf)) == 0)

err = id;

goto out;

}

Page 137: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (3)

case SEM_STAT: buf = arg.buf;

err = -EINVAL;

if (semid > max_semid)

goto out;

sma = semary[semid];

if (sma == IPC_UNUSED || sma == IPC_NOID)

goto out;

err = -EACCES;

if (ipcperms (&sma->sem_perm, S_IRUGO))

goto out;

id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

err = -EFAULT;

if (copy_to_user (buf, &tbuf, sizeof(*buf)) == 0)

err = id;

goto out;

}

Información del semáforo semid.

Page 138: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (3)

case SEM_STAT: buf = arg.buf;

err = -EINVAL;

if (semid > max_semid)

goto out;

sma = semary[semid];

if (sma == IPC_UNUSED || sma == IPC_NOID)

goto out;

err = -EACCES;

if (ipcperms (&sma->sem_perm, S_IRUGO))

goto out;

id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

err = -EFAULT;

if (copy_to_user (buf, &tbuf, sizeof(*buf)) == 0)

err = id;

goto out;

}

Comprueba que tiene acceso de lectura.

Page 139: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (3)

case SEM_STAT: buf = arg.buf;

err = -EINVAL;

if (semid > max_semid)

goto out;

sma = semary[semid];

if (sma == IPC_UNUSED || sma == IPC_NOID)

goto out;

err = -EACCES;

if (ipcperms (&sma->sem_perm, S_IRUGO))

goto out;

id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

err = -EFAULT;

if (copy_to_user (buf, &tbuf, sizeof(*buf)) == 0)

err = id;

goto out;

}

Copia la estructura recién copiada a la memoria de usuario.

Page 140: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (4)

id = (unsigned int) semid % SEMMNI; sma = semary [id];

err = -EINVAL;

if (sma == IPC_UNUSED || sma == IPC_NOID)

goto out;

ipcp = &sma->sem_perm;

nsems = sma->sem_nsems;

err = -EIDRM;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

switch (cmd) {

case GETVAL:

case GETPID:

case GETNCNT:

case GETZCNT:

case SETVAL:

err = -EINVAL;

if (semnum >= nsems)

goto out;

curr = &sma->sem_base[semnum];

break;

}

Page 141: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (4)

id = (unsigned int) semid % SEMMNI; sma = semary [id];

err = -EINVAL;

if (sma == IPC_UNUSED || sma == IPC_NOID)

goto out;

ipcp = &sma->sem_perm;

nsems = sma->sem_nsems;

err = -EIDRM;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

switch (cmd) {

case GETVAL:

case GETPID:

case GETNCNT:

case GETZCNT:

case SETVAL:

err = -EINVAL;

if (semnum >= nsems)

goto out;

curr = &sma->sem_base[semnum];

break;

}

Operan en semáforos individuales porlo que primero se chequea semnum y

si está en rango curr apunta al semáforo correspondiente.

Page 142: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (5)

switch (cmd) { case GETVAL:

case GETPID:

case GETNCNT:

case GETZCNT:

case GETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

switch (cmd) {

case GETVAL : err = curr->semval; goto out;

case GETPID : err = curr->sempid & 0xffff; goto out;

case GETNCNT: err = count_semncnt(sma,semnum); goto out;

case GETZCNT: err = count_semzcnt(sma,semnum); goto out;

case GETALL:

array = arg.array;

break;

}

break;

Page 143: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (5)

switch (cmd) { case GETVAL:

case GETPID:

case GETNCNT:

case GETZCNT:

case GETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

switch (cmd) {

case GETVAL : err = curr->semval; goto out;

case GETPID : err = curr->sempid & 0xffff; goto out;

case GETNCNT: err = count_semncnt(sma,semnum); goto out;

case GETZCNT: err = count_semzcnt(sma,semnum); goto out;

case GETALL:

array = arg.array;

break;

}

break;

Obtiene el valor del semáforo.

Page 144: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (5)

switch (cmd) { case GETVAL:

case GETPID:

case GETNCNT:

case GETZCNT:

case GETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

switch (cmd) {

case GETVAL : err = curr->semval; goto out;

case GETPID : err = curr->sempid & 0xffff; goto out;

case GETNCNT: err = count_semncnt(sma,semnum); goto out;

case GETZCNT: err = count_semzcnt(sma,semnum); goto out;

case GETALL:

array = arg.array;

break;

}

break;

El pid.

Page 145: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (5)

switch (cmd) { case GETVAL:

case GETPID:

case GETNCNT:

case GETZCNT:

case GETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

switch (cmd) {

case GETVAL : err = curr->semval; goto out;

case GETPID : err = curr->sempid & 0xffff; goto out;

case GETNCNT: err = count_semncnt(sma,semnum); goto out;

case GETZCNT: err = count_semzcnt(sma,semnum); goto out;

case GETALL:

array = arg.array;

break;

}

break;

Número de procesos que esperan valor nulo.

Page 146: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (6)

case SETVAL: val = arg.val;

err = -ERANGE;

if (val > SEMVMX || val < 0)

goto out;

break;

case IPC_RMID:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

freeary (id);

err = 0;

goto out;

}

err = -EPERM;

goto out;

case SETALL:

array = arg.array;

err = -EFAULT;

if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))

goto out;

err = 0;

Page 147: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (6)

case SETVAL: val = arg.val;

err = -ERANGE;

if (val > SEMVMX || val < 0)

goto out;

break;

case IPC_RMID:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

freeary (id);

err = 0;

goto out;

}

err = -EPERM;

goto out;

case SETALL:

array = arg.array;

err = -EFAULT;

if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))

goto out;

err = 0;

Permite inicializar un semáforo a un valor

determinado que se especifica en arg.

Page 148: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (6)

case SETVAL: val = arg.val;

err = -ERANGE;

if (val > SEMVMX || val < 0)

goto out;

break;

case IPC_RMID:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

freeary (id);

err = 0;

goto out;

}

err = -EPERM;

goto out;

case SETALL:

array = arg.array;

err = -EFAULT;

if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))

goto out;

err = 0;

Comprueba que el valor está dentro de los valores posibles.

Page 149: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (6)

case SETVAL: val = arg.val;

err = -ERANGE;

if (val > SEMVMX || val < 0)

goto out;

break;

case IPC_RMID:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

freeary (id);

err = 0;

goto out;

}

err = -EPERM;

goto out;

case SETALL:

array = arg.array;

err = -EFAULT;

if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))

goto out;

err = 0;

Liberas el semáforo.

Page 150: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (6)

case SETVAL: val = arg.val;

err = -ERANGE;

if (val > SEMVMX || val < 0)

goto out;

break;

case IPC_RMID:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

freeary (id);

err = 0;

goto out;

}

err = -EPERM;

goto out;

case SETALL:

array = arg.array;

err = -EFAULT;

if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))

goto out;

err = 0;

Inicializas todos los semáforos a un valor.

Page 151: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (6)

case SETVAL: val = arg.val;

err = -ERANGE;

if (val > SEMVMX || val < 0)

goto out;

break;

case IPC_RMID:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

freeary (id);

err = 0;

goto out;

}

err = -EPERM;

goto out;

case SETALL:

array = arg.array;

err = -EFAULT;

if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))

goto out;

err = 0;

Copia los semáforos al espacio de memoria del usuario y comprueba

que ningún valor supere el máximo.

Page 152: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (7)

for (i = 0; i < nsems; i++) if (sem_io[i] > SEMVMX) {

err = -ERANGE;

goto out;

}

break;

case IPC_STAT:

buf = arg.buf;

break;

case IPC_SET:

buf = arg.buf;

err = copy_from_user (&tbuf, buf, sizeof (*buf));

if (err)

err = -EFAULT;

break;

}

err = -EIDRM;

if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)

goto out;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

Page 153: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (7)

for (i = 0; i < nsems; i++) if (sem_io[i] > SEMVMX) {

err = -ERANGE;

goto out;

}

break;

case IPC_STAT:

buf = arg.buf;

break;

case IPC_SET:

buf = arg.buf;

err = copy_from_user (&tbuf, buf, sizeof (*buf));

if (err)

err = -EFAULT;

break;

}

err = -EIDRM;

if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)

goto out;

if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)

goto out;

Modificar ciertos valores de la estructura.

Page 154: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (8)

case SETVAL: err = -EACCES;

if (ipcperms (ipcp, S_IWUGO))

goto out;

for (un = sma->undo; un; un = un->id_next)

un->semadj[semnum] = 0;

curr->semval = val;

sma->sem_ctime = CURRENT_TIME;

update_queue(sma);

break;

case IPC_SET:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

ipcp->uid = tbuf.sem_perm.uid;

ipcp->gid = tbuf.sem_perm.gid;

ipcp->mode = (ipcp->mode & ~S_IRWXUGO)

| (tbuf.sem_perm.mode & S_IRWXUGO);

sma->sem_ctime = CURRENT_TIME;

err = 0;

goto out;

}

err = -EPERM;

goto out;

Page 155: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (8)

case SETVAL: err = -EACCES;

if (ipcperms (ipcp, S_IWUGO))

goto out;

for (un = sma->undo; un; un = un->id_next)

un->semadj[semnum] = 0;

curr->semval = val;

sma->sem_ctime = CURRENT_TIME;

update_queue(sma);

break;

case IPC_SET:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

ipcp->uid = tbuf.sem_perm.uid;

ipcp->gid = tbuf.sem_perm.gid;

ipcp->mode = (ipcp->mode & ~S_IRWXUGO)

| (tbuf.sem_perm.mode & S_IRWXUGO);

sma->sem_ctime = CURRENT_TIME;

err = 0;

goto out;

}

err = -EPERM;

goto out;

Debido a que se le está asignando un nuevo valor,cualquier semnum semáforo es invalidado , para

lo cual el bucle lo pone a cero no tendrán efecto.

Page 156: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (8)

case SETVAL: err = -EACCES;

if (ipcperms (ipcp, S_IWUGO))

goto out;

for (un = sma->undo; un; un = un->id_next)

un->semadj[semnum] = 0;

curr->semval = val;

sma->sem_ctime = CURRENT_TIME;

update_queue(sma);

break;

case IPC_SET:

if (current->euid == ipcp->cuid ||

current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {

ipcp->uid = tbuf.sem_perm.uid;

ipcp->gid = tbuf.sem_perm.gid;

ipcp->mode = (ipcp->mode & ~S_IRWXUGO)

| (tbuf.sem_perm.mode & S_IRWXUGO);

sma->sem_ctime = CURRENT_TIME;

err = 0;

goto out;

}

err = -EPERM;

goto out;

Esto solo puede ser ejecutado por un proceso cuyo euid

es igual al del sem_perm.cuid o sem_perm.uid.

Page 157: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (9)

case IPC_STAT: err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

if (copy_to_user (buf, &tbuf, sizeof(*buf)))

err = -EFAULT;

break;

case SETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IWUGO))

goto out;

for (i = 0; i < nsems; i++)

sma->sem_base[i].semval = sem_io[i];

for (un = sma->undo; un; un = un->id_next)

for (i = 0; i < nsems; i++)

un->semadj[i] = 0;

sma->sem_ctime = CURRENT_TIME;

update_queue(sma);

break;

Page 158: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (9)

case IPC_STAT: err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

if (copy_to_user (buf, &tbuf, sizeof(*buf)))

err = -EFAULT;

break;

case SETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IWUGO))

goto out;

for (i = 0; i < nsems; i++)

sma->sem_base[i].semval = sem_io[i];

for (un = sma->undo; un; un = un->id_next)

for (i = 0; i < nsems; i++)

un->semadj[i] = 0;

sma->sem_ctime = CURRENT_TIME;

update_queue(sma);

break;

Copia la estructura asociada a semid.

Page 159: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (9)

case IPC_STAT: err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

if (copy_to_user (buf, &tbuf, sizeof(*buf)))

err = -EFAULT;

break;

case SETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IWUGO))

goto out;

for (i = 0; i < nsems; i++)

sma->sem_base[i].semval = sem_io[i];

for (un = sma->undo; un; un = un->id_next)

for (i = 0; i < nsems; i++)

un->semadj[i] = 0;

sma->sem_ctime = CURRENT_TIME;

update_queue(sma);

break;

Todos los valores de los semáforos son puestos

con el valor del llamante.

Page 160: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (9)

case IPC_STAT: err = -EACCES;

if (ipcperms (ipcp, S_IRUGO))

goto out;

tbuf.sem_perm = sma->sem_perm;

tbuf.sem_otime = sma->sem_otime;

tbuf.sem_ctime = sma->sem_ctime;

tbuf.sem_nsems = sma->sem_nsems;

if (copy_to_user (buf, &tbuf, sizeof(*buf)))

err = -EFAULT;

break;

case SETALL:

err = -EACCES;

if (ipcperms (ipcp, S_IWUGO))

goto out;

for (i = 0; i < nsems; i++)

sma->sem_base[i].semval = sem_io[i];

for (un = sma->undo; un; un = un->id_next)

for (i = 0; i < nsems; i++)

un->semadj[i] = 0;

sma->sem_ctime = CURRENT_TIME;

update_queue(sma);

break;Para todo ajuste undo relacionado al semáforo es puesto a cero.

Page 161: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (10)

default:

err = -EINVAL;

goto out;

}

err = 0;

out:

unlock_kernel();

return err;

}

Page 162: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (10)

default:

err = -EINVAL;

goto out;

}

err = 0;

out:

unlock_kernel();

return err;

}

Operación no reconocida.

Page 163: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

“ipc/sem.c//sys_semctl” (10)

default:

err = -EINVAL;

goto out;

}

err = 0;

out:

unlock_kernel();

return err;

}

Operación no reconocida.

Page 164: IPC : SEMÁFOROS. Carmelo Quintana Hernández, a3182@dis.ulpgc.es a3182@dis.ulpgc.es Miguel Ramírez Alemán a3183@dis.ulpgc.es

FIN.