Nowe posty

xx Problem ze sterownikami. (5)
2024-04-13, 21:25:16
xx Instalacja xfce4 (2)
2024-04-13, 16:20:17
xx Serie kompilacji bez instalacji dla “emerge” w Gentoo (2)
2024-04-08, 18:40:04
xx Plasma 6 w Neonie ssie trochę mniej ... (17)
2024-04-05, 10:03:46
xx Problem z Linux Lite po instalacji (3)
2024-04-03, 14:23:40
xx Jak właczyć num locka przy starcie systemu debian 12? (12)
2024-04-02, 17:43:54
xx Brak dźwieku w systemie. (5)
2024-04-02, 16:13:41
xx Dystrybucja pod HP Omen (7)
2024-03-29, 11:33:05
xx [Poradnik] Wyszukiwanie Sterowników (2)
2024-03-27, 21:08:23
xx Ile pingwinów? (1)
2024-03-27, 08:59:24

Autor Wątek: [C] Synchronizacja wątków. Problem producentów i konsumentów.  (Przeczytany 7195 razy)

megotpelka

  • Gość
Witam.
Problem który ma rozwiązać to znane zagadnienie z dziedziny synchronizacji wątków dla 4 producentów i 4 konsumentów. Dodatkowo mamy dodany wątek kontrolny, drukarz który ma co jakiś czas wydrukować bufor.
A teraz troszkę o kodzie:
- mamy 3 obszary pamięci współdzielonej: na bufor danych, semafory, oraz strukturę przekazywaną do wątku
- każdy dostaje unikatowe ID dzięki funkcji ftok()
- synchronizacja (odpowiednia kolejność podnoszenia i opuszczania semaforów) zaczerpnięta z sieci
Przy próbie uruchomienia otrzymuję błąd: segmentation fault
Prosiłbym o wskazanie ewentualnych błędów lub innego sposobu rozwiązania problemu.

PS. Nie ukrywam że program pisałem bezpośrednio po implementacji zagadnienia na Win, więc mogłem sugerować się tamtym kodem.
 
#include 
#include
#include
#include
#include
#include
#include

#define N 100         /* rozmiar współdzielonej tablicy */

struct dane
{
int num;
int pos;
struct sembuf op;
int semid;
int *tab;
};

void konsument(void * arg)
{
struct dane *moje_dane = (struct dane *)arg;

while(1)
{
/* podniesienie semafora producenta */
moje_dane->op.sem_num = 0;  
moje_dane->op.sem_op = 1;
semop(moje_dane->semid, &moje_dane->op, 1);

/* opuszczenie semafora ochrony */
moje_dane->op.sem_num = 2;  
moje_dane->op.sem_op = -1;
semop(moje_dane->semid, &moje_dane->op, 1);

int i = 0;
while(i != 70000000) //opoznienie okolo 3s dzialajace lepiej niz sleep
{i++;}

/* odczyt elementu z tablicy */
printf("Z pozycji %d odczytałem %d\\n", moje_dane->pos, moje_dane->tab[moje_dane->pos]);
moje_dane->pos = (moje_dane->pos + 1) % N;

/* podniesienie semafora ochrony */
moje_dane->op.sem_num = 2;  
moje_dane->op.sem_op = 1;
semop(moje_dane->semid, &moje_dane->op, 1);

/* opuszczenie semafora konsumenta */
moje_dane->op.sem_num = 1;  
moje_dane->op.sem_op = -1;
semop(moje_dane->semid, &moje_dane->op, 1);
}
}

void producent(void * arg)
{
struct dane *moje_dane = (struct dane *)arg;
while(1)
{
/* opuszczenie semafora producenta */
moje_dane->op.sem_num = 0;  
moje_dane->op.sem_op = -1;
semop(moje_dane->semid, &moje_dane->op, 1);

/* opuszczenie semafora ochrony */
moje_dane->op.sem_num = 2;  
moje_dane->op.sem_op = -1;
semop(moje_dane->semid, &moje_dane->op, 1);

int i = 0;
while(i != 70000000) //opoznienie okolo 3s dzialajace lepiej niz sleep
{i++;}

/* zapis elementu do tablicy */
moje_dane->tab[moje_dane->pos] = moje_dane->num;
printf("Na pozycji %d zapisałem %d\\n", moje_dane->pos, moje_dane->num);
moje_dane->pos = (moje_dane->pos + 1) % N;
moje_dane->num++;

/* podniesienie semafora ochrony */
moje_dane->op.sem_num = 2;  
moje_dane->op.sem_op = 1;
semop(moje_dane->semid, &moje_dane->op, 1);

/* podniesienie semafora konsumenta */
moje_dane->op.sem_num = 1;  
moje_dane->op.sem_op = 1;
semop(moje_dane->semid, &moje_dane->op, 1);
}
}

void drukarz(void * arg)
{
struct dane *moje_dane = (struct dane *)arg;
while(1)
{
int i;
for(i=0;i {
printf("%d ",moje_dane->tab[i]);
}
printf("\\n");

i = 0;
while(i != 70000000)
{i++;}
}
}

int main(void)
{
int i;
int shmid1, shmid2;         /* systemowy identyfikator bloku pamięci dzielonej */
int semid;         /* systemowy identyfikator semafora */
struct sembuf op;  /* struktura dla operacji na semaforze */

key_t key1 = ftok(".", 'a'); //generowanie unikatowego ID dla obszaru pamieci
key_t key2 = ftok(".", 'b');
key_t key3 = ftok(".", 'c');

const size_t rozmiar1 = sizeof(struct dane);  //wyznacznie rozmiaru pamieci na dane dzielone

shmid1 = shmget(key1, rozmiar1, 0744 | IPC_CREAT);
 
 if (shmid1 == -1)
 {
printf("ERROR\\n");
 }
 
 struct dane* data = shmat(shmid1, NULL, 0);
 memset(data, 0, rozmiar1);
 
 const size_t rozmiar2 = (N -1) * sizeof(int);

 shmid2 = shmget(key2, rozmiar2, 0744 | IPC_CREAT);
 
 if (shmid2 == -1)
 {
printf("ERROR\\n");
 }
 
 int *tab = shmat(shmid2, NULL, 0);
 memset(tab, 0, rozmiar2);
 
/* utworzenie nowego dwuelementowego semafora
  * 0 - semafor producenta
  * 1 - semafor konsumenta
  * 2 - semafor ochrony dostepu do operacji na tablicy
  */
 
 semid = semget(key3, 3, 0700 | IPC_CREAT);
 
 if (semid == -1)
 {
printf("ERROR\\n");
 }
 
 /* ustawienie wartości początkowych semaforów */
 
 semctl(semid, 0, SETVAL, 1);
 semctl(semid, 1, SETVAL, 1);
 semctl(semid, 2, SETVAL, 1);

pthread_t producent[4];
pthread_t konsument[4];
pthread_t drukarz;


data->op = op;
data->tab = tab;
data->semid = semid;
data->pos = 0;
data->num =0;

for (i = 0; i < 4; i++)
{
if( pthread_create( &producent[i], NULL, producent, data) )
printf("blad przy tworzeniu watku\\n");
}
for (i = 0; i < 4; i++)
{
if(pthread_create( &konsument[i], NULL, konsument, data))
printf("blad przy tworzeniu watku\\n");
}

if(pthread_create( &drukarz, NULL, drukarz, data))
printf("blad przy tworzeniu watku\\n");

shmdt(data);
shmdt(tab);

return 0;
}

ZipoKing

  • Gość
[C] Synchronizacja wątków. Problem producentów i konsumentów.
« Odpowiedź #1 dnia: 2010-04-25, 19:24:31 »
Błąd segmentacji pamięci z reguły powodowany jest w przypadku próby odwołania się do obszaru pamięci, do którego nie mamy dostępu. Próbowałeś np. przy pomocy gdb znaleźć miejsce gdzie program się wysypuje?

chmooreck

  • Gość
[C] Synchronizacja wątków. Problem producentów i konsumentów.
« Odpowiedź #2 dnia: 2010-04-25, 21:35:06 »
Wypadałoby może jakiś cywilizowany sposób zakończyć wątki i poczekać aż się skończą w głównym programie, nie uważasz ?
Pod jakim względem taka pętla opóźniająca ma działać lepiej niż sleep()/usleep(). Jest to marnotrawienie zasobów.

megotpelka

  • Gość
[C] Synchronizacja wątków. Problem producentów i konsumentów.
« Odpowiedź #3 dnia: 2010-04-26, 22:11:43 »
Reading symbols from /home/task/Pulpit/PR_5/kod.o...done.
(gdb) run
Starting program: /home/task/Pulpit/PR_5/kod.o
[Thread debugging using libthread_db enabled]
[New Thread 0xb7fecb70 (LWP 1574)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7fecb70 (LWP 1574)]
0x00133807 in start_thread () from /lib/tls/i686/cmov/libpthread.so.0
I daje gdy dałem up:

#1 0x002138de in clone () from /lib/tls/i686/cmov/libc.so.6
Initial frame selected; you cannot go up.
Kompilowałem z flagą -g

chmooreck

  • Gość
[C] Synchronizacja wątków. Problem producentów i konsumentów.
« Odpowiedź #4 dnia: 2010-04-26, 22:52:17 »
bt