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)