Problem wzajemnego wykluczania z użyciem semaforów

Odpowiedz Nowy wątek
2018-05-09 20:49
0

Witam ponownie. Jestem w trakcie pisania programu związanego z problemem wzajemnego wykluczania. Niestety, mimo iż program został napisany wg algorytmu, który znalazłem, proces proces.x w ogóle nie wchodzi do sekcji krytycznej. Prosiłbym o podpowiedź, gdzie należy szukać błędu, co zostało napisane nie tak. Przyznaję, że średnio rozumiem temat semaforów. Poniżej zamieszczam kod:

powielacz.c - tworzy zadaną przez użytkownika liczbę procesów (drugi argument wywołania) w oparciu o nazwę pliku (pierwszy argument):

#include "func.h"
#define BASE 0          //trzeci argument funkcji strtol
#define PATH_SIZE 25    //maksymalna długość ścieżki
#define PN_WSK 2        //przesunięcie wskaźnika na tablicę path
#define FIRST_CHARS "./"
#define VAL 1

int main(int argc, char const *argv[])
{
    if (argc<3) //liczba argumentow wywolania
    {
        perror("Zbyt mala liczba argumentow wywolania!\nProsze uruchomic program ponownie, z wlasciwa liczba arugmentow.\n");
        exit(6);
    }

    const int syg_nr=strtol(argv[2], NULL, BASE);   //liczba procesów
    char path[PATH_SIZE]=FIRST_CHARS;  //ścieżka poprzedzona znakami "./"
    int key;    //klucz
    int id_sem; //ID zbioru

    if(syg_nr==-1)  //błędny pierwszy argument
    {
        perror("Blad funkcji strtol()\n");
        exit(8);
    }

    if(syg_nr<=1)   //błędny drugi argument
    {
        perror("Liczba procesow musi byc wieksza niż 1!\nProsze o ponowne uruchomienie programu z poprawnym parametrem.\n");
        exit(6);
    }

    if(sscanf(argv[1], "%s", path+PN_WSK)==-1)  //pierwszy argument
    {
        perror("Blad funkcji sscanf()\n");
        exit(7);
    }

    key=semAccess();        //uzyskanie dostępu
    id_sem=createSem(key);  //utworzenie zbioru
    setValue(id_sem, VAL);  //przypisanie wartości

    for(int i=1; i<=syg_nr; i++)
    {
        const int child_pid=fork();

        if(child_pid==-1)
        {
            fprintf(stderr, "Nie udalo sie utworzyc procesu potomnego o numerze: %d.\n", i);
            exit(9);
        }
        else if(child_pid==0)
        {
            if(execl(path, argv[1], NULL)==-1)
            {
                perror("Blad funkcji exec()\n");
                exit(10);
            }            
        }
        sleep(4);
    }

    semDelete(id_sem);

    return 0;
}

proces.c - program, który wrzucam do powielacza:

#include "func.h"
#define LOOP_TM 5   //liczba wejść do sekcji krytycznej

int main(int argc, char const *argv[])
{
    key_t key;  //klucz do zbioru semaforów
    const int pid=getpid(); //ID procesu
    int id_sem; //ID zbioru semaforów

    key=semAccess();    //uzyskanie klucza do zbioru semaforów
    id_sem=createSem(key);  //utworzenie zbioru

    for(int i=1; i<=LOOP_TM; i++)
    {
        down(id_sem);
        printf("Proces o ID: %d uzyskal dostep do sekcji krytycznej po raz: %d\n", pid, i);
        sleep(1);
        printf("Proces o ID: %d opuszcza sekcje krytyczna po raz: %d\n", pid, i);
        up(id_sem);
        sleep(1);
        printf("Proces o ID: %d przeszedl do sekcji reszty po raz: %d\n", pid, i);
    }
    //5-krotne przejście procesu do sekcji krytycznej
    //oraz wyjście z niej
    //zgodnie z algorytmem zamieszczonym w materiałach

    printf("Proces %d opuscil petle...\n", pid);    //komunikat końcowy procesu

    return 0;
}

func.c:

#include "func.h"
#define SEM_NR 1            //liczba semaforów
#define MODE 0666           //tryb
#define SEM0 0              //nr semafora w zbiorze
#define PATH "./proces.x"   //ścieżka pliku dla funkcji ftok()

int createSem(key_t key)
{
    int semid;
    semid=semget(key, SEM_NR, IPC_CREAT|IPC_EXCL|MODE);
    //if(==-1);
    //{
      //  perror("Blad funkcji createSem()\n");
        //exit(4);
    //}
    return semid;
}

void setValue(int semid, int val)
{
    union semun ctrl;
    ctrl.val=val;
    if(semctl(semid, SEM0, SETVAL, ctrl)==-1)  //SETVAL orzymuje wartość 1
    {
        perror("Blad funkcji setValue()\n");
        exit(5);
    }
}

void up(int semid)
{
    struct sembuf do_op = {0, 1, 0};
    //struktura zawiera kolejno: nr semafora, operację, flagę
    //czyli: semnum, sem_op, sem_flg
    //0 - operacja blokująca
    if(semop(semid, &do_op, SEM_NR)==-1)
    {
        perror("Blad funkcji up()\n");
        exit(2);
    }
}

void down(int semid)
{
    struct sembuf do_op = {0, -1, 0};
    if(semop(semid, &do_op, SEM_NR)==-1)
    {
        perror("Blad funkcji down()\n");
        exit(2);
    }
}

void semDelete(int semid)   //usuwanie semafora
{
    if(semctl(semid, SEM0, IPC_RMID)==-1)   //obsługa błędów
    {
        perror("Blad funkcji semDelete\n");
        exit(1);
    }
    else    //komunikat
    {
        printf("Semafor zostal usuniety\n");
    }
}

key_t semAccess()   //uzyskanie dostępu do semafora
{
    int key;
    if((key=ftok(PATH, getpid()))==-1)
    {
        perror("Blad funkcji semAccess()\n");
        exit(3);
    }
    return key;
}

func.h:

#ifndef FUNC_H
#define FUNC_H

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

#ifdef _SEM_SEMUN_UNDEFINED

union semun {
int val;                    //wartosc dla SETVAL
struct semid_ds *buf;       //bufor dla IPC_STAT, IPC_SET
unsigned short *array;      //tablica dla GETALL, SETALL
struct seminfo *__buf;      //bufor dla IPC_INFO (specyfika Linuksa)
};

#endif  //_SEM_SEMUN_UNDEFINED

int createSem(key_t key);   //utworzenie semafora
void setValue(int semid, int val);   //przypisanie wartośći (inicjalizacja)
void up(int semid);         //podniesienie semafora...
void down(int semid);       //...i jego opuszczenie
key_t semAccess();          //dostęp do semafora
//int queue(int semid);       //kolejka
void semDelete(int semid);  //usunięcie semafora

#endif  //FUNC_H

W func.c funkcja createSem() miała mieć obsługę błędów, ale gdy ją dodaję, kompilator ostrzega o warunku, który nie chroni, a program zwraca błąd: "Blad funkcji createSem(): Success".

edytowany 2x, ostatnio: furious programming, 2018-05-09 20:50
Pozdrów Wilka :D, ale szanuję, że robisz te projekty sam. - Czitels 2018-05-19 09:45

Pozostało 580 znaków

2018-05-10 00:25

Masz poprawiony kod co nieco. Generalnie problem był z tym, że niepotrzebnie dawałeś 0660.

#include "func.h"
#define SEM_NR 1            //liczba semaforów
#define MODE 0600          //tryb
#define SEM0 0            //nr semafora w zbiorze
#define PATH "./proces.x"   //ścieżka pliku dla funkcji ftok()

int
createSem(key_t key, int flags)
{
    int semid;

    semid = semget(key, SEM_NR, flags);
    if (semid == -1) {
        perror("Blad funkcji createSem()\n");
        exit(4);
    }
    return semid;
}

void
setValue(int semid, int val)
{
    union semun ctrl;

    ctrl.val = val;
    if (semctl(semid, SEM0, SETVAL, ctrl) == -1) {
        perror("Blad funkcji setValue()\n");
        exit(5);
    }
}

void
up(int semid)
{
    struct sembuf do_op = {
        .sem_num = 0,
        .sem_op = 1,
        .sem_flg = 0
    };

    if (semop(semid, &do_op, SEM_NR) == -1) {
        perror("Blad funkcji up()\n");
        exit(2);
    }
}

void
down(int semid)
{
    struct sembuf do_op = {
        .sem_num = 0,
        .sem_op = -1,
        .sem_flg = 0
    };

    if (semop(semid, &do_op, SEM_NR) == -1) {
        perror("Blad funkcji down()\n");
        exit(2);
    }
}

void
semDelete(int semid)
{

    if (semctl(semid, SEM0, IPC_RMID) == -1) {
        perror("Blad funkcji semDelete\n");
        exit(1);
    }
    else {
        printf("Semafor zostal usuniety\n");
    }
}

key_t
semAccess()
{
    key_t key;
    key = ftok(PATH, 1);
    if (key == -1) {
        perror("Blad funkcji semAccess()\n");
        exit(3);
    }
    return key;
}
#include <sys/types.h>
#include <sys/wait.h>

#include <errno.h>
#include "func.h"
#define BASE 0        //trzeci argument funkcji strtol
#define PATH_SIZE 255   //maksymalna długość ścieżki
#define VAL 1

int
main(int argc, char *argv[])
{
    int nchildren;
    char *endptr;
    int key;
    int id_sem;

    if (argc < 3) {
        fprintf(stderr, "Zbyt mala liczba argumentow wywolania!\nProsze uruchomic program ponownie, z wlasciwa liczba arugmentow.\n");
        exit(1);
    }

    nchildren = strtol(argv[2], &endptr, 10);
    if (*endptr != '\0' || errno == EINVAL) {
        fprintf(stderr, "Invalid number: %s\n", argv[2]);
        exit(2);
    }

    if (nchildren <= 1) {
        fprintf(stderr, "Liczba procesow musi byc wieksza niż 1!\nProsze o ponowne uruchomienie programu z poprawnym parametrem.\n");
        exit(4);
    }

    key = semAccess();
    id_sem = createSem(key, IPC_CREAT | SEM_R | SEM_A);
    setValue(id_sem, VAL);

    for(int i; i < nchildren; i++)
    {
        const int pid = fork();

        if (pid == -1) {
            fprintf(stderr, "Nie udalo sie utworzyc procesu potomnego o numerze: %d.\n", i);
            exit(9);
        } else if (pid == 0) {
            if (execlp(argv[1], argv[1], NULL) == -1) {
                perror("Blad funkcji exec()\n");
                exit(10);
            }
        }
        sleep(4);
    }

    for (int i = 0; i < nchildren; i++) {
        pid_t child;
        int status;

        child = wait(&status);
        printf("Child %d finished with code %d\n", child, status);
    }

    semDelete(id_sem);

    return 0;
}
#include "func.h"
#define LOOP_TM 5   //liczba wejść do sekcji krytycznej

int
main(int argc, char *argv[])
{
    key_t key;  //klucz do zbioru semaforów
    const int pid = getpid(); //ID procesu
    int id_sem; //ID zbioru semaforów

    key = semAccess();  //uzyskanie klucza do zbioru semaforów
    id_sem = createSem(key, IPC_CREAT | SEM_R | SEM_A);  //utworzenie zbioru

    for (int i = 1; i <= LOOP_TM; i++) {
        down(id_sem);
        printf("Proces o ID: %d uzyskal dostep do sekcji krytycznej po raz: %d\n", pid, i);
        sleep(1);
        printf("Proces o ID: %d opuszcza sekcje krytyczna po raz: %d\n", pid, i);
        up(id_sem);
        sleep(1);
        printf("Proces o ID: %d przeszedl do sekcji reszty po raz: %d\n", pid, i);
    }
    //5-krotne przejście procesu do sekcji krytycznej
    //oraz wyjście z niej
    //zgodnie z algorytmem zamieszczonym w materiałach

    printf("Proces %d opuscil petle...\n", pid);    //komunikat końcowy procesu

    return 0;
}
#ifndef FUNC_H
#define FUNC_H

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>

#ifdef _SEM_SEMUN_UNDEFINED

union semun {
int val;                    //wartosc dla SETVAL
struct semid_ds *buf;       //bufor dla IPC_STAT, IPC_SET
unsigned short *array;      //tablica dla GETALL, SETALL
struct seminfo *__buf;      //bufor dla IPC_INFO (specyfika Linuksa)
};

#endif  //_SEM_SEMUN_UNDEFINED

int createSem(key_t key, int flags);   //utworzenie semafora
void setValue(int semid, int val);   //przypisanie wartośći (inicjalizacja)
void up(int semid);         //podniesienie semafora...
void down(int semid);       //...i jego opuszczenie
key_t semAccess();          //dostęp do semafora
//int queue(int semid);       //kolejka
void semDelete(int semid);  //usunięcie semafora

#endif  //FUNC_H

Pozostało 580 znaków

2018-05-12 19:02
0

@kapojot: Wielkie dzięki. Mógłbyś mi jeszcze wyjaśnić, co oznaczają flagi SEM_R oraz SEM_A? Nigdzie nie mogę znaleźć informacji na ich temat.

edytowany 1x, ostatnio: nojaniewiem, 2018-05-12 19:38

Pozostało 580 znaków

2018-05-14 00:36
1

Dostęp do semafora R/W dla użytkownika i grupy. https://www.freebsd.org/cgi/man.cgi?query=semget&sektion=2

Pozostało 580 znaków

2018-05-18 13:27
0

Jeszcze raz wielkie dzięki :)

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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