Politechnika Świętokrzyska
Laboratorium programowania współbieżnego
Temat:
Pamięć dzielona
Grupa 314A:
Salwa Rafał
Data wykonania ćwiczenia:
21.11.2011
Data oddania sprawozdania:
22.11.2011
1. Napisać program który:
•
stworzy segment pamięci dzielonej o wielkości pozwalającej na zapis zmiennej typu long
•
tworzy n=10 lub 100 procesów za pomocą funkcji fork
•
procesy potomne m=1000000 (lub więcej) razy pobierają wartość przechowywaną w
pamięci dzielonej, zwiększają ją o 1 i zapisują wynik
•
wypisze wynik sumy powstałej w pamięci dzielonej. Czy otrzymana liczba wynosi
dokładnie mxn?
•
do programu dodać semafor ograniczający dostęp do zmiennej dzielonej
•
operacja pobierania i dodawania i zapisywania zmiennej dzielonej powinna znaleźć się w
sekcji krytycznej. Czy teraz po uruchomieniu programu otrzymana wartość to mxn?
•
wyjaśnić dlaczego tak się dzieje
2. Kod Programu
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>
#define n 10
#define m 1000000
#define SEMKEYPATH argv[0]
#define SEMKEYID 1
#define SHMKEYPATH argv[0]
#define SHMKEYID 1
#define NUMSEMS 2
#define SHMSIZE sizeof(long)
#define NUMMSG 2
static struct sembuf op_lock[1] = {
0, -1, 0
};
static struct sembuf op_unlock[1] = {
0, 1, 0
};
void
opusc (int semid)
{
if (semop (semid, &op_lock[0], 1) < 0)
perror ("blad lokowania semafora");
}
void
podnies (int semid)
{
if (semop (semid, &op_unlock[0], 1) < 0)
perror ("blad odlokowania semafora");
}
int
main (int argc, char **argv)
{
int shmmid = 0;
unsigned long *shmptr;
int chpid = 0;
int i = 0;
int rc, semid, shmid;
key_t semkey, shmkey;
void *shm_address;
short sarray[NUMSEMS];
semkey = ftok (SEMKEYPATH, SEMKEYID);
if (semkey == -1)
perror ("ftok sem");
printf ("\nsemkey %d\n", semkey);
shmkey = ftok (SHMKEYPATH, SHMKEYID);
if (shmkey == -1)
perror ("ftok shm");
printf ("shmkey %d\n", shmkey);
semid = semget (semkey, NUMSEMS, 0666 | IPC_CREAT);
if (semid == -1)
perror ("semget: ");
sarray[0] = 0;
sarray[1] = 0;
rc = semctl (semid, 1, SETALL, sarray);
if (rc == -1)
perror ("semctl: ");
shmmid = shmget (shmkey, SHMSIZE, 0666 | IPC_CREAT);
if (shmmid == -1)
perror ("shmget: ");
shm_address = shmat (shmid, NULL, 0);
if (shm_address == NULL)
perror ("shmat: ");
podnies (semid);
for (i = 1; (i <= n) && (chpid = fork ()); i++);
if (!chpid)
{
int j;
long *shmptr;
shmptr = shmat (shmmid, NULL, 0);
for (j = 0; j < m; j++)
{
opusc (semid);
shmptr[0] += 1;
podnies (semid);
}
if (shmdt (shmptr) == -1)
perror ("shmdt");
return 0;
}
printf ("Utworzono %d potomkow;\n", i - 1);
for (i = 0; i < n; i++)
wait (NULL);
shmptr = shmat (shmmid, NULL, 0);
printf ("zaw pam dzielonej = %ld\n", shmptr[0]);
if (shmdt (shmptr) == -1)
perror ("shmdt");
if (shmctl (shmmid, IPC_RMID, NULL) == -1)
perror ("shmctl");
return 0;
}
Wnioski:
dzięki tej instrukcji nauczyliśmy się wykorzystywać pamięć dzieloną jak i też utrwaliliśmy sobie
informacje o zasadzie działania semaforów.
Podczas tworzenia oraz uruchamiania tego programu zauważyłem że, w programie bez semafora
dochodzi do zjawiska przeplotu operacji przez co wynik nie jest równy mxn,dzieje sie tak ponieważ
pare procesów naraz uzyskuje dostep do zmiennej dzielonej.natomiast po zastosowaniu semafora
procesy kolejno uzyskiwały dostęp do zmiennej dzielonej przez co program pracował znacznie
dłużej ale w zamian dostaliśmy poprawny wynik (mxn).