Politechnika Świętokrzyska w Kielcach |
---|
Programowanie Współbieżne |
Laboratorium 6: Semafory |
Kamil Śliwa Grupa 312A |
Data wykonania ćwiczenia: 20.12.2012r. |
Zadanie 2 – Funkcja ftok
Kod źródłowy:
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
int main() {
key_t klucz;
klucz = ftok("/tmp/",3); //plik musi być bo jak nie to ftok zwróci -1
printf("ftok 0x%X\n",klucz);
return 0;
}
Uruchomienie programu:
ubuntu@ubuntu:~$ gcc zad2.c -o zad2 -Wall
ubuntu@ubuntu:~$ ./zad2
ftok 0x3060002
ubuntu@ubuntu:~$
Wyniki uzyskane z podanymi argumentami funkcji ftok dla nazwy programu zad2:
ftok("/tmp/",3); ftok 0x3060002
ftok("/tmp/",20); ftok 0x14060002
ftok("eliza/",3); ftok 0x3148682
ftok("eliza/",20); ftok 0x14148682
Wyniki uzyskane z podanymi argumentami funkcji ftok dla nazwy programu zad2b:
ftok("/tmp/",3); ftok 0x3060002
Jak widać wpływ na wartość unikalnego klucza mają argumenty funkcji ftok, ich zmiana powoduje zmianę unikalnego klucza.
Natomiast jeśli zmienimy tylko nazwę programu to unikalny klucz się nie zmienia.
Zadanie 3 – Semafory
Kod źródłowy:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define PERMS 0666
/*
// wersja podstawowa
static struct sembuf op_lock[1] = {{0, -1, 0}};
static struct sembuf op_unlock[1] = {{0, 1, 0}};
*/
// wersja zmieniona
static struct sembuf op_lock[2] = {
{0,0,0}, /* czekaj, aż semafor nr 0 stanie się zerem */
{0,1,0} /* następnie zwiększ ten semafor 1*/
};
static struct sembuf op_unlock[1] = {{
0, -1, IPC_NOWAIT /* zmniejsz semafor nr 0 o 1 bez czekania bo to zwolnienie zasobów */
}
};
void blokuj(int semid) {
// w wersji podstawowej w funkcji semop ostatni argument ustawic na 1 (zamiast 2)
if (semop(semid, &op_lock[0], 2)<0)
perror("blad blokowania semafora");
}
void odblokuj(int semid) {
if (semop(semid, &op_unlock[0], 1) < 0)
perror("blad odlokowania semafora");
}
int main() {
int semid = -1; // identyfikator semafora
int co;
int jeszcze;
if ((semid = semget(ftok("/tmp",0), 1, IPC_CREAT | PERMS)) < 0)
perror("blad tworzenia semafora");
printf("Podaj Polecenie\n 1 - podnies semafor\n 2 - opusc semafor\n 0 - wyjscie\n");
for (jeszcze = 1; jeszcze;) {
scanf("%d",&co);
printf("wybrano %d\n",co);
switch(co) {
case 2: {
printf("przed blokuj\n");
blokuj(semid);
printf("po blokuj\n");
break;
}
case 1: {
printf("przed odblokuj\n");
odblokuj(semid);
printf("po odblokuj\n");
break;
}
case 0: {
jeszcze = 0;
break;
}
default: {
printf("nie rozpoznana komenda %d\n",co);
}
}
}
return 0;
}
Uruchomienie programu dla wersji zmienionej (zmodyfikowane tablice operacji):
Terminal 1:
ubuntu@ubuntu:~$ gcc zad3.c -o zad3 -Wall
ubuntu@ubuntu:~$ ./zad3
Podaj Polecenie
1 - podnies semafor
2 - opusc semafor
0 - wyjscie
2
wybrano 2
przed blokuj
po blokuj
2
wybrano 2
przed blokuj
(czekanie na odblokowanie)
po blokuj
0
wybrano 0
ubuntu@ubuntu:~$
Terminal 2:
ubuntu@ubuntu:~$ ./zad3
Podaj Polecenie
1 - podnies semafor
2 - opusc semafor
0 - wyjscie
1
wybrano 1
przed odblokuj
po odblokuj
1
wybrano 1
przed odblokuj
po odblokuj
1
wybrano 1
przed odblokuj
blad odlokowania semafora: Resource temporarily unavailable
po odblokuj
0
wybrano 0
ubuntu@ubuntu:~$
Po modyfikacji programu widać ze najpierw semafor trzeba opuścić żeby go móc potem podnieść, inaczej wystąpi błąd.
Opis działania wersji podstawowej według kroków z instrukcji:
Podniesienie 1 wyszło bez błędu, podniesienie 2 również bez błędu. Operacje opuszczenia możemy wykonać 2 razy (ponieważ 2 razy semafor był podniesiony). Przy trzecim opuszczeniu semafor się zablokował. Otwieramy terminal 2 i tam podnosimy semafor, na terminalu 1 semafor się odblokował. Ponownie na terminalu 1 opuszczamy semafor, na terminalu 2 program czeka na nasza decyzje wiec opuszczamy semafor. Teraz na terminalach 1 i 2 semafory są zablokowane. Otwieramy terminal 3 i podnosimy semafor, na terminalu 1 semafor się odblokował, na terminalu 2 nadal jest zablokowany. Podnosimy ponownie semafor na terminalu 3, na terminalu 2 semafor się odblokował. Teraz na wszystkich trzech terminalach można wyjść z programu przez 0.
Sprawdzamy komenda ipcs czy semafor został w systemie, następnie usuwamy go komenda ipcrm -s.
Po zmodyfikowaniu tablicy operacji tak by operacja opuszczania semafora była nie blokująca (IPC_NOWAIT) po uruchomieniu programu i próbie zablokowania semafora wyskoczył błąd, więc można wywnioskować, że z ustawioną flagą IPC_NOWAIT semafor najpierw musi być podniesiony a następnie opuszczony aby nie było błędu. Usuwamy semafor ipcs/ipcrm -s, usuwamy IPC_NOWAIT.
Uruchamiamy podstawowy program i podnosimy semafor kilka razy i wychodzimy przez ^C. Nie usuwając semafora uruchamiamy program ponownie i próbujemy opuścić semafor. Można opuszczać semafor więc widać ze stan semafora został zapamiętany. Usuwamy semafor ipcs/ipcrm -s.
Modyfikujemy tablice operacji dodając opcje SEM_UNDO. Uruchamiamy program, podnosimy kilka razy semafor i wychodzimy przez ^C. Następnie uruchamiamy ponownie program i próbujemy opuścić semafor. Semafor się zablokował wiec widać, że stan semafora nie został zapamiętany. Usuwamy semafor ipcs/ipcrm -s.
Zadanie 3 – Usuwanie semaforów
Kod źródłowy:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define PERMS 0666
int main() {
int semid = -1; // identyfikator semafora
if ((semid = semget(ftok("/tmp",0), 0, PERMS)) < 0)
perror("blad odczytu semafora");
if (semctl(semid, 0, IPC_RMID, 0)==0) printf("Usunieto semafor o id = %d\n",semid);
else perror("blad usuwania semafora");
return 0;
}
Uruchomienie programu:
ubuntu@ubuntu:~$ gcc zad3.c -o zad3 -Wall
ubuntu@ubuntu:~$ gcc zad3b.c -o zad3b -Wall
ubuntu@ubuntu:~$ ./zad3
Podaj Polecenie
1 - podnies semafor
2 - opusc semafor
0 - wyjscie
0
wybrano 0
ubuntu@ubuntu:~$ ipcs
------ Semaphore Arrays --------
key semid owner perms nsems
0x00010003 294912 ubuntu 666 1
ubuntu@ubuntu:~$ ./zad3b
Usunieto semafor o id = 294912
ubuntu@ubuntu:~$ ipcs
------ Semaphore Arrays --------
key semid owner perms nsems
ubuntu@ubuntu:~$
Wnioski
Na zajęciach poznaliśmy zasadę tworzenia unikalnego klucza oraz zasady działania semaforów.
Pisanie programów polegało na odpowiedniej modyfikacji programów z instrukcji. Wszystkie założone cele udało się wykonać bez większych problemów.