#include sys/types.h> #include sys/ipc.h> #include sys/shm.h

Anuncio
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
...
#define SHMKEY 12
#define SEMKEY 12
#define K 1024
#define XM 20
#define YM 20
#define NUM_SEMAFOROS 1
int shmId, semId;
...
char *addr1;
typedef struct {
// Estructura de los datos a ubicar
// en el area compartida
int
numero1,
numero2;
char Msg[100][100];
int M[100][100];
} AreaCompartida;
AreaCompartida *pAC;
struct sembuf psembuf, vsembuf; //
//
//
//
void cleanup();
void quienSoy();
Utilizados para
definir los comandos
para operar en los
semaforos
main()
{
...
short initArray[NUM_SEMAFOROS], outArray[NUM_SEMAFOROS];
//1. Captura de señales
signal (1, quienSoy); //
//
signal (2, cleanup); //
signal (3, cleanup); //
//2.
//
//
//
//
//
//
//
//
//
ante señal HUP, el proceso
se identificará
con estas señales,
el proceso terminará
Instanciación de un area de memoria compartida
entre este proceso y sus procesos hijos:
2.1 Creacion de un area de memoria compartida
identificada por el tag SHMKEY
(SHMKEY = 12 en este ejemplo)
el tamaño es 64K, y podra ser leida y/o escrita
por procesos pertenecientes a cualquier usuario
(permisos 777 corresp. a u,g,o, respectivamente,
interpretados similarmente a los permisos de
los archivos de unix
shmId = shmget(SHMKEY, 64*K, 0777|IPC_CREAT);
1/3
//
//
//
//
2.2 La instrucción siguiente efectúa el attachment del
area compartida recien creada al espacio de memoria de
este proceso (y en consecuencia tambien al area de
memoria de los procesos hijos de este)
addr1 = shmat(shmId, 0, 0);
// 2.3 A continuación obtenemos un pointer al primer
// elemento del area compartida, para poder nombrarla
pAC = (AreaCompartida *) addr1;
//
//
//
//
3. Instanciacion de un semaforo
3.1 Creacion de un semaforo que luego usaremos para
controlar el acceso a elementos ubicados
en el area de memoria compartida
semId = semget(SEMKEY, 1, 0777|IPC_CREAT);
initArray[0] = 1; // preparo esta variable para
// inicializar el valor del
// semaforo: "1" significará
// "resource unlocked"
// 3.2
Inicialización del valor del semaforo (a 1)
semctl (semId, 1, SETALL, initArray);
// forma de leer el (o los) valor(e)s del semaforo:
semctl (semId, 1, GETALL, outArray);
printf("Valor inicial del semaforo: [%d]\n",
outArray[0] );
// 3.3 Preparar 2 structs para operar sobre el primer
// semaforo del array (en este caso, el único)
psembuf.sem_num= 0; // primer semaforo del array
// la operacion "-1" corresponderá, para nosotros, a la
// función de "reservar recurso"
psembuf.sem_op= -1;
psembuf.sem_flg = SEM_UNDO;
vsembuf.sem_num= 0; // primer semaforo del array
// la operacion "+1" corresponderá a la función de
// "liberar recurso"
vsembuf.sem_op= 1;
vsembuf.sem_flg = SEM_UNDO;
// 4. Creacion de algunos procesos "hijo"
childNo = 0;
for (j=0; j<XM; j++) // spawn XM hijos
{
r=random();
k = fork();
if (k==0) execChild();
printf("Se creo proc. child P%d, pid %d.\n",
childNo, k); // Parent notifica
childNo++;
}
NoChildren = childNo;
childNo=-1;
// El proceso parent quedará
// identificado con "-1"
2/3
// 5. Loop infinito del proceso parent
// (sale mediante algún signal handler)
while (1)
{
printMatrix(1);
sleep(1);
}
} // end main()
void cleanup() // Handler de terminación, libera ambas
// estructuras (shared mem y semaforo)
{
shmctl(shmId, IPC_RMID, 0); // destruye shared memory
semctl(semId, IPC_RMID, 0); // destruye semaforo
printf("Fin del signal handler 'CLEANUP' \n");
exit();
}
void quienSoy() // Handler para SIGHUP - el proceso que
// la recibe imprime su Id y termina
{
sprintf(pAC->Msg[childNo], "Yo era P%d\n", childNo);
exit();
}
execChild()
{
// Programa básico para los procesos "child", con
// ejemplo de locking de recurso compartido
int m;
while(1)
{
// 5.1 Obtenemos un "lock" usando el semáforo (primitiva
// P de Dijkstra). La primitiva "P" se bloquea hasta que
// logra obtener el semáforo (o sea, en este caso,
// ponerlo a 0 habiendo estado en 1)
semop(semId, &psembuf, 1);
//
//
//
//
//
//
//
Cuando se sale de P, sabemos que somos los únicos
que estamos corriendo con el semáforo en "1"
y en consecuencia tenemos el derecho de alterar la
memoria compartida (este derecho está acordado
cooperativamente entre los procesos que emplean el
semáforo, pero no está "garantizado" por el sistema
operativo.
// 5.2 Alteramos el área de memoria compartida (en este
// ejemplo, un elemento de una matriz)
m = ++(pAC->M[childNo][childNo]);
//
//
//
//
//
5.3 Liberamos el lock (operacion "V" de Dijkstra). Al
hacerlo, se despierta uno (sólo uno) de los procesos
que eventualmente hayan estado esperando por el lock
(o sea, que hubieran estado dormidos sobre la
primitiva "P", ver 5.1)
semop(semId, &vsembuf, 1);
}
}
3/3
Descargar