background image

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
 };

background image

 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: ");

background image

  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).