Informatiker Board (http://www.informatikerboard.de/board/index.php)
- Themengebiete (http://www.informatikerboard.de/board/board.php?boardid=1)
--- Praktische Informatik (http://www.informatikerboard.de/board/board.php?boardid=6)
---- Algorithmen (http://www.informatikerboard.de/board/board.php?boardid=17)
----- Aufgabe mit Semaphoren (http://www.informatikerboard.de/board/thread.php?threadid=2337)


Geschrieben von deppensido am 10.06.2015 um 23:02:

  Aufgabe mit Semaphoren

Hallo,

bei der Aufgabe (siehe Anhang) ist mir nicht klar, ob es zu Problemen bzgl der Ent-/Belademenge führen kann. Ich habe einige Prozessablauffolgen durchprobiert, aber meiner Meinung nach, passt das alles. Kann ich daraus schließen, dass es wirklich nicht zu Problemen kommen kann (3. Teil der Aufgabe).

Im folgenden poste ich mal meine Lösungen zu Teil 1 und 2. Habe ich hier alles richtig gemacht?

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
1)

benötigte Semaphoren: 

mutex(1) //damit die Laderampe nur von jeweils einem Prozess gleichzeitig verwendet werden kann, zu beginn ist die Laderampe frei 

empty(24) //zaehlt die entnommenen Teile der Lagerhalle, zu beginn ist die Lagerhalle leer → Platz für 24 Teile

Nachfolgende Semaphoren sind je mit 0 initialisiert, da die Lagerhalle zu beginn leer ist
server(0) // zählt die vorhandenen Server

dektoprechner(0) // zählt die vorhandenen DesktopRechner

monitor(0) // zählt die vorhandenen Monitore



2)

Prozess H
while(true) :
	for i=1 to 6 do
		P(empty) //Die Ware muss komplett abgeladen werden können (6 Teile)
	P(mutex) // Laderampe muss frei sein (kritischen Bereich betreten)
	Server_entladen(1)
	DesktopRechner_entladen(3)
	Monitore_entladen(2)
	V(mutex) //Laderampe verlassen (kritischen Bereich verlassen)
	V(server) // 1 Server wurde entladen
	for i=1 to 3 do
		V(desktoprechner) // 3 DesktopRechner wurden entladen
	V(monitor)
	V(monitor) //2 Monitore wurden entladen
	
	
Prozess D
while(true) :
	P(desktoprechner)
	P(monitor) // Es muss mindestens 1 DesktopRechner und 1 Monitor im Lager sein
	P(mutex) // Laderampe muss frei sein (kritischen Bereich betreten)
	DesktopRechner_entladen(1)
	Monitore_entladen(1)
	V(mutex) //Laderampe verlassen (kritischen Bereich verlassen)
	V(empty)
	V(empty) //Anzahl der entnommenen Teile um 2 erhöhen





Prozess S
while(true) :
	P(server) // es muss mindestens ein Server im Lager sein
	P(mutex) // Laderampe muss frei sein (kritischen Bereich betreten)
	Server_entladen(1)
	V(mutex) // Laderampe verlassen (kritischen Bereich verlassen)
	V(empty) // Anzahl der entnommenen Teile um 1 erhöhen


vielen Dank im voraus.



Geschrieben von deppensido am 11.06.2015 um 01:54:

 

ich habe mich nun an den letzten Teil der Aufgabe gemacht, also das Beispiel mit posix_threads in C implementiert. Allerdings bekomme ich es nicht hin das Programm auszuführen.
Meine Idee war zuerst "gcc Blatt5.c -lpthread" auszuführen und dann "gcc -o Blatt5 Blatt5.c" das erste lief noch Fehlerlos, beim zweiten bekomme ich einen Haufen Warnungen und Fehler. Wenn ich dann "gdb Blatt5" eingebe, kommt die Meldung "Datei oder Verzeichnis nicht gefunden. Ich arbeite übrigens über OpenSuse und nutze einen Texteditor (Kate) zum schreiben der Programme. Das Ausführen mach ich dann über das Terminal. Die Datei habe ich einfach Blatt5.c genannt.

Im folgenden mal der Code:
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#define BUFFER_SIZE 24
//benötigte semaphoren
sem_t empty;
sem_t server;
sem_t desktoprechner;
sem_t monitor;
pthread_mutex_t mutex;

pthread_attr_t attr;

pthread_t ptid,dtid,stid; //Threads für 3 Prozesse

void *producerH(void *param);
void *consumerD(void *param);
void *consumerS(void *param);

int serverCount=0;
int desktoprechnerCount=0;
int monitorCount=0;

int criticalSectionCountH=0;
int criticalSectionCountD=0;
int criticalSectionCountS=0;

int main()
{
  //semaphoren initialisieren
  pthread_mutex_init(&mutex, NULL);
  pthread_attr_init(&attr);
  sem_init(&server, 0, 0);
  sem_init(&desktoprechner, 0, 0);
  sem_init(&monitor, 0, 0);
  sem_init(&empty, 0, BUFFER_SIZE);
  
  //Threads erstellen
  pthread_create(&ptid, &attr, producerH, NULL);
  pthread_create(&dtid, &attr, consumerD, NULL);
  pthread_create(&stid, &attr, consumerS, NULL);
  //darauf warten, dass die Threads fertig sind
  pthread_join(ptid,NULL);
  pthread_join(dtid,NULL);
  pthread_join(stid,NULL);
  
  printf("%d mal im kritischen Bereich des Herstellers gewesen\n", criticalSectionCountH);
  printf("%d mal im kritischen Bereich des Techniker D gewesen\n", criticalSectionCountD);
  printf("%d mal im kritischen Bereich des Techniker S gewesen\n", criticalSectionCountS);

  return 0;
}


void *producerH(void *param)
{
  while(1)
  {
    int i;
    for(i=0;i<6;i++)
	sem_wait(&empty);
    pthread_mutex_lock(&mutex);
    criticalSectionCountH++;
    serverCount++;
    desktoprechnerCount = desktoprechnerCount + 3;
    monitorCount = monitorCount + 2;
    printf("%d Server entladen\n",serverCount);
    printf("%d desktoprechner entladen\n",desktoprechnerCount);
    printf("%d Monitore entladen\n",monitor);
    pthread_mutex_unlock(&mutex);
    sem_post(&server);
    sem_post(&desktoprechner);
    sem_post(&desktoprechner);
    sem_post(&desktoprechner);
    sem_post(&monitor);
    sem_post(&monitor);
  }
}

void *consumerD(void *param)
{
  while(1)
  {
    sem_wait(&desktoprechner);
    sem_wait(&monitor);
    pthread_mutex_lock(&mutex);
    criticalSectionCountD++;
    monitorCount--;
    desktoprechnerCount--;
    printf("%d desktoprechner beladen\n",desktoprechnerCount);
    printf("%d Monitore beladen\n",monitor);
    pthread_mutex_unlock(&mutex);
    sem_post(&empty);
    sem_post(&empty);
  }
}

void *consumerS(void *param)
{
  while(1)
  {
    sem_wait(&server);
    pthread_mutex_lock(&mutex);
    criticalSectionCountS++;
    serverCount--;
    printf("%d Server beladen\n",serverCount);
    pthread_mutex_unlock(&mutex);
    sem_post(&empty);
  }
}


Ist da vielleicht doch am Code was falsch oder muss ich es nur anders ausführen?
Ich kann mir jedenfalls nicht erklären, was am Code falsch sein könnte.
Vielen Dank im voraus.



Geschrieben von deppensido am 11.06.2015 um 02:02:

 

ich habe die Fehlermeldungen mal angehängt. Alle verweisen auf fehlende Referenzen, aber die sollten durch #include <pthread.h> und #include <semaphore.h> doch gegeben sein?



Geschrieben von eulerscheZahl am 11.06.2015 um 16:12:

 

Also, bei mir schluckt der Compiler das gcc blatt5.c -pthread (Ubuntu).

code:
1:
2:
3:
4:
5:
6:
7:
8:
gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 



Geschrieben von deppensido am 11.06.2015 um 16:46:

 

danke,

bei mir klappt es jetzt auch. Ich musste über gcc -pthread Blatt5.c kompilieren, dann ist im Projektordner eine a.out Datei entstanden, die ich per Aktionen -> run in Konsole ausführen kann. Das ging also diesmal etwas anders als, wie ich es sonst gemacht hatte, daher die Probleme. Habe die Ausgaben noch etwas angepasst, sodass das Programm das gewünschte Verhalten ausgibt. Hier braucht also wohl nichts mehr verbessert werden. Scheint alles korrekt zu sein.


Forensoftware: Burning Board, entwickelt von WoltLab GmbH