5 filozofów kolejki komunikatów C

0

Witam,
Mam na zadanie Problem 5 filozofów na kolejkach komunikatów rozwiązanie na stanach w języku C. Napisałem program dla filozofa oraz main na podstawie pseudo kodu, który mieliśmy w skrypcie i który załączam na dole. Problem jest w tym, że program działa do pewnego momentu, i po jakimś czasie już nic się nie dzieje. Tak jakby cała kolejka się zwolniła, nie wiem w czym jest problem gdyż kod pisałem w oparciu o pseudokod ze skryptu. Proszę o jakieś wskazówki co mogę robić źle i czemu tak się dzieje.

Pseudo kod wygląda następująco:

stan[i]=0 – myślenie
stan[i]=1 – chęć jedzenia
stan[i]=2 – jedzenie
var widelec: array[0..4] of recource;
sem: array[0..4] of Boolean semaphore:=false;
stan: array[0..4] of integer:=0; /myślenie
w: Boolean semaphore:=true;
procedure test(k:integer);
begin
if stan[(k-1) mod 5]<>2 and stan[k]=1 and stan[(k+1) mod 5]<>2
then
stan[k]:=2;
signal(sem[k]);
end
end

Kod filozofa:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>

#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>

#define PHIL_COUNT 5

#define fil 5
#define W 15

void thinking();
void eating();
void showForks();

struct msgStructure
{
    long msgType;
    int mVal;
};

key_t widelceKolejkaKlucz;
key_t filozofKolejkaKlucz;

key_t memKey;

int widelceID;
int filozofyID;

int philID;
int memID;

int *stan; //tablica widelcow
int i;
int loops;
struct msgStructure message;


void test(int nr_filozofa) {

    if(stan[(nr_filozofa-1)%5] != 2 && stan[nr_filozofa] == 1 && stan[(nr_filozofa+1)%5] !=2)
    {
        stan[nr_filozofa - 1] =2;
        message.msgType = nr_filozofa;
        msgsnd(filozofyID, &message, sizeof(message.mVal), 0);
    }
}

int main(int argc, char *argv[])
{

    philID = atoi(argv[2]);
    loops = atoi(argv[1]);

    srand(time(NULL));


    if ((widelceKolejkaKlucz = ftok(".", 'A')) == -1) {
        fprintf(stderr, "Linia %d: ftok(queueKey) zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((filozofKolejkaKlucz = ftok(".", 'C')) == -1) {
        fprintf(stderr, "Linia %d: ftok(queueKey) zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((widelceID=msgget(widelceKolejkaKlucz,0666)) == -1) {
        fprintf(stderr, "Linia %d: msgget zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((filozofyID=msgget(filozofKolejkaKlucz, 0666)) == -1) {
        fprintf(stderr, "Linia %d: msgget zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((memKey = ftok(".", 'B')) == -1)
    {
        fprintf(stderr, "Linia %d: ftok(memKey) zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((memID = shmget(memKey, PHIL_COUNT*sizeof(int), 0666))==-1)
    {
        fprintf(stderr, "Linia %d: shmget zakonczony bledem: %d\n",__LINE__, errno);
        exit(EXIT_FAILURE);
    }

    fflush(stdout);

    if ((stan = (int*)shmat(memID, NULL, 0)) == (int*) - 1)
    {
        fprintf(stderr, "Linia %d: shmat zakonczony bledem: %d\n", __LINE__,  errno);
        exit(EXIT_FAILURE);
    }



    for (i = 0; i < loops; i++)
    {
        thinking(); //myslenie
        msgrcv(filozofyID, &message, sizeof(message.mVal), W, 0); //wait(w)
        //    stan[philID-1] = 1; // stan[name]:=1
			stan[philID] = 1;	

       //     test(philID-1); // test(name)
			test(philID);
        message.msgType = W;

        msgsnd(filozofyID, &message, sizeof(message.mVal), 0); //signal(w)

        showForks();

        msgrcv(filozofyID, &message, sizeof(message.mVal), philID, 0); // wait(sem[name])
       // request (widelec[name],widelec[(name+1)mod5]);
        msgrcv(widelceID, &message, sizeof(message.mVal), philID, 0);
        msgrcv(widelceID, &message, sizeof(message.mVal), (philID+1)%6, 0);
        //=================================================
        //jedzenie;
        eating();
        //release(widelec[name],widelec[(name+1)mod5]);
        message.msgType = philID;
        msgsnd(widelceID, &message, sizeof(message.mVal), 0);
        message.msgType = (philID+1) % 6;
        msgsnd(widelceID, &message, sizeof(message.mVal), 0);
        //=========================================
        msgrcv(filozofyID, &message, sizeof(message.mVal), W, 0); //wait(w)
        stan[philID-1] = 0; //stan[name]:=0;
        test((philID+1)%6);//test((name+1)mod 5);
      //  test(philID==1 ? 4 : philID-2);//test((name-1)mod 5);
      	test((philID-1)%6);
        showForks();

        message.msgType = W;
        msgsnd(filozofyID, &message, sizeof(message.mVal), 0); //signal(w)




       /* int leftFork, rightFork;
        if (philID==1)
        {
            msgrcv(queueID, &message, sizeof(message.mVal), 1, 0); //lewy
            leftFork=1;
            rightFork=5;
            msgrcv(queueID, &message, sizeof(message.mVal), 5, 0); //prawy
        }
        else
        {
            msgrcv(queueID, &message, sizeof(message.mVal), philID-1, 0); //prawy
            msgrcv(queueID, &message, sizeof(message.mVal), philID, 0); //lewy
            leftFork=philID;
            rightFork=philID-1;
        }

        pForksTab[leftFork-1] = philID;
        pForksTab[rightFork-1] = philID;

        eating();

        message.msgType = leftFork;
        msgsnd(queueID, &message, sizeof(message.mVal), 0);
        message.msgType = rightFork;
        msgsnd(queueID, &message, sizeof(message.mVal), 0);

        pForksTab[leftFork-1] = 0;
        pForksTab[rightFork-1] = 0;
        */
    }
}

void thinking()
{
    printf("Filozof %d mysli\n", philID);
    sleep(rand()%4);

}

void eating()
{
    printf("___________________\nFilozof %d je... \n", philID);
    sleep(1);
    showForks();
    printf("Filozof %d skonczyl jesc.\n", philID);
}

void showForks()
{
    int i;
    printf("\nTablica stanow: ");
    for (i = 0; i < PHIL_COUNT; i++)
        printf("  %d  ", stan[i]);
    printf("\n");
}


A kod pliku main tak:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>

#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <signal.h>

#define PHIL_COUNT 5
#define W 15

struct msgStructure
{
    long msgType;
    int mVal;
};

key_t widelceKolejkaKlucz;
key_t filozofKolejkaKlucz;

key_t memKey;

int widelceID;
int filozofyID;

int philID;
int memID;

int *pForksTab; //tablica widelcow

void sig_handler(int signo)
{
    if (signo != SIGINT)
        return;
    msgctl(widelceID, IPC_RMID, NULL);
    msgctl(filozofyID, IPC_RMID, NULL);
    exit(EXIT_SUCCESS);
}
int main(int argc, char *argv[])
{
    int i;
    int philID = 1;
    struct msgStructure message;
    char argument[2];

    signal(SIGINT, sig_handler);
    printf("Ustawianie...\n");

    if ((widelceKolejkaKlucz = ftok(".", 'A')) == -1) {
        fprintf(stderr, "Linia %d: ftok(queueKey) zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((filozofKolejkaKlucz = ftok(".", 'C')) == -1) {
        fprintf(stderr, "Linia %d: ftok(queueKey) zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((widelceID=msgget(widelceKolejkaKlucz, IPC_CREAT|0666)) == -1) {
        fprintf(stderr, "Linia %d: msgget zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((filozofyID=msgget(filozofKolejkaKlucz, IPC_CREAT|0666)) == -1) {
        fprintf(stderr, "Linia %d: msgget zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    for (i = 1; i <= PHIL_COUNT; i++) {
        message.msgType=i;
        msgsnd(widelceID, &message, sizeof(message.mVal), 0);
    }

    message.msgType=W; //ustawianie pseudo-semafora na 1
    msgsnd(filozofyID, &message, sizeof(message.mVal), 0);


    if ((memKey=ftok(".", 'B')) == -1) {
        fprintf(stderr, "Linia %d: Liftok(memKey) zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((memID=shmget(memKey, PHIL_COUNT*sizeof(int), IPC_CREAT|0666)) == -1) {
        fprintf(stderr, "Linia %d: shmget zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    if ((pForksTab = (int*)shmat(memID, NULL, 0)) == (int*) - 1) {
        fprintf(stderr, "Linia %d: shmat zakonczony bledem: %d\n", __LINE__, errno);
        exit(EXIT_FAILURE);
    }

    for (i=0; i<PHIL_COUNT; i++)
        pForksTab[i]=0;


    printf("Tworzenie procesow filozofow.\n");
    for (i=1; i<=PHIL_COUNT; i++)
        switch (fork()) {
        case -1:
            fprintf(stderr, "Linia %d: Fork zakonczony bledem", __LINE__);
            exit(EXIT_FAILURE);
        case 0:
            sprintf(argument, "%d", i);
            execl("./filozof", "filozof", "10", argument, NULL);
        }

    for (i=1; i<=PHIL_COUNT; i++)
        wait(NULL);

    sig_handler(SIGINT);
    printf("MAIN: Koniec.\n");



}
0

Zapomniałem dodać tą część pseudokodu, dałem tylko funkcji testującej. Mój błąd

procedure filozof;
begin
repeat
myślenie;
wait(w);
stan[name]:=1;
test(name);
signal(w);
wait(sem[name]);
request (widelec[name],widelec[(name+1)mod5]);
jedzenie;
release(widelec[name],widelec[(name+1)mod5]);
wait(w);
stan[name]:=0;
test((name+1)mod 5);
test((name-1)mod 5);
signal(w)
end
end;

0

Podbijam temat, czy wie któś jak powinno wyglądać to zadanie. Temat stary ale wciąż bez odpowiedzi.

0

@biały Kot, Z czym masz konkretnie problem?

0

Odswieżam

0

Nie sprawdzasz kodów błędu a możesz dostać coś jak EAGAIN. Nie zawsze masz mod5 przy dostepie do tablicy stanów a nr-1 bez mod5 wyjdzie ujemny ... Nie synchronuzujesz odczytów na tablicy stanów ... Nie chodzi tylko o to kto może czytać i pisać ale czy dane zostaną wywalone z casha, nie ma żadnej bariery na pamięci (semafor wstawia barierę niejawnie).

1 użytkowników online, w tym zalogowanych: 0, gości: 1