NOMBRE¶
semop - operaciones con semáforos
SINTAXIS¶
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf
*sops, unsigned nsops);
DESCRIPCIÓN¶
Un semáforo se representa por una estructura anónima que incluye los
siguientes miembros:
unsigned short semval; /* valor del semáforo */
unsigned short semzcnt; /* # esperando por cero */
unsigned short semncnt; /* # esperando por incremento */
pid_t sempid; /* proceso que hizo la última operación */
La función
semop realiza operaciones sobre los miembros
seleccionados del conjunto de semáforos indicado por
semid. Cada
uno de los
nsops elementos en el array apuntado por
sops
especifica una operación a ser realizada en un semáforo mediante una
estructura
sembuf que incluye los siguientes miembros:
unsigned short sem_num; /* número de semáforo */
short sem_op; /* operación sobre el semáforo */
short sem_flg; /* banderas o indicadores para la operación */
Banderas reconocidas en
sem_flg son
IPC_NOWAIT y
SEM_UNDO.
Si una operación ejecuta
SEM_UNDO, sera deshecha cuando el proceso
finalice.
El conjunto de operaciones contenido en
sops se realiza de forma
atómica, es decir, las operaciones son llevadas a cabo al mismo
tiempo, y sólo si pueden ser realizadas simultáneamente. El
comportamiento de la llamada al sistema en caso de que no todas las
operaciones puedan realizarse inmediatamente depende de la presencia de la
bandera
IPC_NOWAIT en los campos
sem_flg individuales, como se
ve más abajo.
Cada operación es ejecutada en el semáforo numero
sem_num donde
el primer semáforo del conjunto es el semáforo
0. Hay tres
tipos de operación, que se distinguen por el valor de
sem_op.
Si
sem_op es un entero positivo, la operación añade este valor
al valor del semáforo (
semval)
. Además, si
SEM_UNDO es invocado para esta operación, el sistema actualiza el
contador del proceso para operaciones "undo" (
semadj) para
este semáforo. La operación siempre puede ejecutarse - nunca fuerza
a un proceso a esperar. El proceso invocador debe tener permisos de
modificación sobre el conjunto de semáforos.
Si
sem_op es cero, el proceso debe tener permiso de lectura en el
semáforo. Esta es una operación "espera-por-cero": si
semval es cero, la operación puede ejecutarse inmediatamente. Por
otra parte, si
IPC_NOWAIT es invocado en
sem_flg, la llamada al
sistema falla con la variable
errno fijada a
EAGAIN . (y ninguna
de las operaciones
sops se realiza.) En otro caso
semzcnt (el
número de procesos esperando hasta que el valor del semáforo sea
cero) es incremetada en uno y el proceso duerme hasta que algo de lo siguiente
ocurra:
- •
- semval es 0, instante en el que el valor de
semzcnt es decrementeado.
- •
- El semáforo es eliminado: la llamada al sistema falla
con errno fijada a EIDRM.
- •
- El proceso que lo invoca captura una señal: el valor
de semzcnt es decrementado y la llamada al sistema falla con
errno fijada a EINTR.
Si
sem_op es menor que cero, el proceso debe tener los permisos de
modificación sobre el semáforo. Si
semval es mayor que o
igual que el valor absoluto de
sem_op, la operación puede
ejecutarse inmediatamente: el valor absoluto de
sem_op es restado a
semval. y, si
SEM_UNDO es invocado para esta operación, el
sistema actualiza el contador "undo" del proceso (
semadj)
para este semáforo. Si el valor absoluto de
sem_op es mayor que
semval, y
IPC_NOWAIT está presente en
sem_flg, la
llamada al sistema falla con
errno fijado a
EAGAIN. (y ninguna
de las operaciones
sops se realiza.) En otro caso
semncnt (el
número de procesos esperando a que se incremente el valor de este
semáforo) es incrementado en uno y el proceso duerme hasta que ocurra:
- •
- semval sea mayor o igual que el valor absoluto de
sem_op, en cuyo instante el valor de semncnt es
decrementado, el valor absoluto de sem_op es restado de
semval y, si SEM_UNDO es invocado para esta operación,
el sistema actualiza el contador "undo" del proceso
(semadj) para este semáforo.
- •
- El semáforo es es eliminado del sistema: la llamada al
sistema falla con errno fijado a EIDRM.
- •
- El proceso invocador captura una señal: el valor de
semncnt es decrementado y la llamada al sistema falla con
errno fijado a EINTR.
En caso de que haya funcionado, el valor
sempid para cada semáforo
especificado en el array apuntado por
sops es fijado al identificador
del proceso del proceso invocador. Además
sem_otime es puesto a la
hora actual.
VALOR DEVUELTO¶
Si todo ha sido correcto la llamada al sistema devuelve
0, en otro caso
devuelve
-1 con
errno indicando el error.
ERRORES¶
En caso de error
errno tendrá uno de los siguientes valores:
- E2BIG
- El argumento nsops es mayor que SEMOPM, el
numero máximo de operaciones permitidas por llamada del sistema.
- EACCES
- El proceso invocador no tiene permisos de acceso al
semáforo como se requiere por una de las operaciones
especificadas.
- EAGAIN
- Una operación no puede ser ejecutada inmediatamente y
IPC_NOWAIT ha sido invocada en su sem_flg.
- EFAULT
- La direccion apuntada por sops no es accesible.
- EFBIG
- Para algunas operaciones el valor de sem_num es
menor que 0 o mayor o igual que el numero de semáforos en el
conjunto.
- EIDRM
- El conjunto de semáforos ha sido eliminado.
- EINTR
- Mientras estaba bloqueado en esta llamada al sistema, el
proceso capturó una señal.
- EINVAL
- Este conjunto de semáforos no existe, o semid
es menor que cero, o nsops tiene un valor no-positivo.
- ENOMEM
- El sem_flg de alguna operación invoco
SEM_UNDO y el sistema no tiene suficiente memoria para alojar la
estructura "undo".
- ERANGE
- Para alguna operacion sem_op+semval es mayor que
SEMVMX, el valor máximo dependiente de la implementación
para semval.
OBSERVACIONES¶
Las estructuras
sem_undo de un proceso no son heredadas tras la
ejecución de
fork(2) , pero sí tras la ejecución de
execve(2).
semop no es reiniciada nunca automáticamente
después de haber sido interrumpida por un manejador de señales, sin
importar que las banderas
SA_RESTART estén presentes cuando se
establezca el manejador señales.
semadj es un entero por cada proceso que representa simplemente el
número (negativo) de todas las operaciones sobre semáforos
realizadas con la bandera
SEM_UNDO. Cuando se establece directamente el
valor de un semáforo usando la solicitud
SETVAL o
SETALL en
semctl(2), los correspondientes valores de
semadj en todos los
procesos son borrados.
Los valores
semval,
sempid,
semzcnt, y
semnct para
un semáforo pueden ser obtenidos usando llamadas
semctl(2)
apropiadas.
Los siguientes valores son limites en el conjunto de recursos de los
semáforos q ue afecta a
semop
- SEMOPM
- Numero máximo de operaciones permitidas para una
llamada (32) semop.
- SEMVMX
- Valor máximo permitido para semval: dependiente
de la implementación (32767).
La implementación no contiene límites intrínsecos para ajustar el
valor máximo de la salida (
SEMAEM), el numero máximo de
estructuras "undo" que el sistema permite (
SEMMNU) y
máximo numero de entradas "undo" por proceso para los
parametros del sistema.
FALLOS¶
Cuando un proceso termina, su conjunto de estructuras
semadj asociado se
utiliza para deshacer el efecto de todas las operaciones sobre semáforos
que realizó con la bandera
SEM_UNDO. Esto conlleva una dificultad:
si una (o más) de estas modificaciones sobre semáforos resultara en
un intento de decrementar el valor de un semáforo por debajo de cero,
¿qué debería hacer una implementación? Una posible
aproximación sería bloquearse hasta que todas las modificaciones
sobre semáforos puedan ser realizadas. Esto no es deseable sin embargo
puesto que podría bloquear la terminación del proceso durante largos
períodos arbitrarios. Otra posibilidad sería ignorar tales
modificaciones sobre semáforos por completo (algo análogo a un fallo
cuando se especifica
IPC_NOWAIT para una operación sobre
semáforos). Linux adopta un tercer enfoque: decrementar el valor del
semáforo tanto como sea posible (p.e., hasta cero) y permitir la
terminación del proceso inmediatamente.
SVr4, SVID. SVr4 documenta las condiciones de error adicionales EINVAL, EFBIG,
ENOSPC.
VÉASE TAMBIÉN¶
ipc(5),
semctl(2),
semget(2),
sigaction(2)