[c]Utilizzo corretto dei semafori comunicazione tra processi

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Tino-Tom
Prode Principiante
Messaggi: 68
Iscrizione: venerdì 29 agosto 2014, 13:00
Distribuzione: Ubuntu 64bit

[c]Utilizzo corretto dei semafori comunicazione tra processi

Messaggio da Tino-Tom »

Salve a tutti, sto cercando di creare un programma in C che faccia la seguente : Il mio programma prevede che il processo padre legga un file di testo preso da riga di comando e ne legga il contenuto riga per riga passandole al processo figlio. Il processo figlio legge le righe ricevute, le converte in maiuscolo e le ripassa al padre. I processi comunicano mediante un segmento di memoria condivisa e un certo numero di semafori. Entrambi dovranno indicare la fine del file.

Ecco il mio codice

Codice: Seleziona tutto

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <ctype.h>

#define DIM 1024

#define MUTEX 0 // sem mutex
#define FULL 1  // sem full
#define EMPTY 2 // sem empty

#define MUTEX2 3 // sem mutex
#define FULL2 4  // sem full
#define EMPTY2 5 // sem empty

#define TYPE_P 2
#define TYPE_F 3
#define TYPE_FN 4

typedef struct
{
  char text[DIM];
  long type;
} msg;

int WAIT(int sem_id, int sem_num)
{
  struct sembuf ops[1] = {{sem_num, -1, 0}};
  return semop(sem_id, ops, 1);
}

int SIGNAL(int sem_id, int sem_num)
{
  struct sembuf ops[1] = {{sem_num, +1, 0}};
  return semop(sem_id, ops, 1);
}

void father(int shm_id, int sem_id, char *filename, msg *p)
{
  FILE *r_stream;
  char tmp[DIM];

  if ((r_stream = fopen(filename, "r")) == NULL)
  {
    perror("fopen");
    exit(1);
  }

  while (fgets(tmp, DIM, r_stream) != NULL)
  {
    printf("Father -> %s", tmp);
    WAIT(sem_id, EMPTY);
    WAIT(sem_id, MUTEX);
    strcpy(p->text, tmp);
    p->type = TYPE_F;

    SIGNAL(sem_id, MUTEX);
    SIGNAL(sem_id, FULL);
  }

  WAIT(sem_id, EMPTY);
  WAIT(sem_id, MUTEX);
  strcpy(p->text, "EOF");
  p->type = TYPE_F;
  SIGNAL(sem_id, MUTEX);
  SIGNAL(sem_id, FULL);

  fclose(r_stream);

  printf("father final\n");

  int done = 0;
  while (done == 0)
  {
    WAIT(sem_id, FULL2);
    WAIT(sem_id, MUTEX2);

    strcpy(tmp, p->text);

    SIGNAL(sem_id, MUTEX2);
    SIGNAL(sem_id, EMPTY2);

    printf("Father final: %s",tmp);

    if (strcmp(tmp, "EOF") == 0)
      done = 1;
  }
}

void filter(int shm_id, int sem_id, int child, msg *p, char *word)
{

  int done = 0;
  while (done == 0)
  {

    char text[DIM];

    WAIT(sem_id, FULL);
    WAIT(sem_id, MUTEX);

    strcpy(text, p->text);

    SIGNAL(sem_id, MUTEX);
    SIGNAL(sem_id, EMPTY);

    if (strcmp(text, "EOF") != 0)
    {

      printf("\tFilter-> %s", text);

      for (int i = 0; i < strlen(text); i++)
      {
        text[i] = toupper(text[i]);
      }

      WAIT(sem_id, EMPTY2);
      WAIT(sem_id, MUTEX2);

      strcpy(p->text, text);

      SIGNAL(sem_id, MUTEX2);
      SIGNAL(sem_id, FULL2);
    }
    else
    {
      SIGNAL(sem_id, MUTEX2);
      SIGNAL(sem_id, FULL2);
      strcpy(p->text, "EOF");
      SIGNAL(sem_id, MUTEX2);
      SIGNAL(sem_id, FULL2);

      done = 1;
    }

  }

  exit(0);
}

int main(int argc, char *argv[])
{
  /* code */
  int shm_id, sem_id, shm_id2;
  msg *p, *p2;

  if (argc == 1 || argc == 2)
  {
    fprintf(stderr, "uso: %s file.txt filter-1...filte-n \n", argv[0]);
    exit(1);
  }

  // creo area di memoria condivisa
  if ((shm_id = shmget(IPC_PRIVATE, sizeof(msg), IPC_CREAT | 0600)) == -1)
  {
    perror("shmget");
    exit(1);
  }

  // attacco area di memoria
  if ((p = (msg *)shmat(shm_id, NULL, 0)) == (msg *)-1)
  {
    perror("shmat");
    exit(1);
  }

  // creo i semafori
  if ((sem_id = semget(IPC_PRIVATE, 3, IPC_CREAT | 0600)) == -1)
  {
    perror("semget");
    exit(1);
  }

  // inizializzo semafori
  semctl(sem_id, MUTEX, SETVAL, 1);
  semctl(sem_id, EMPTY, SETVAL, 1);
  semctl(sem_id, FULL, SETVAL, 0);
  semctl(sem_id, MUTEX2, SETVAL, 1);
  semctl(sem_id, EMPTY2, SETVAL, 1);
  semctl(sem_id, FULL2, SETVAL, 0);

  int child = argc - 2;
  char *filename = argv[1];
  char *word = argv[2];

  if (fork() == 0)
  {

    filter(shm_id, sem_id, child, p, word);
  }
  else
  {
    father(shm_id, sem_id, filename, p);
    // distruggo area di memoria condivisa
    wait(NULL);
    shmctl(shm_id, IPC_RMID, NULL);
    // rimuovo i semafoti
    semctl(sem_id, FULL, IPC_RMID, 0);
    semctl(sem_id, EMPTY, IPC_RMID, 0);
    semctl(sem_id, MUTEX, IPC_RMID, 0);
    semctl(sem_id, FULL2, IPC_RMID, 0);
    semctl(sem_id, EMPTY2, IPC_RMID, 0);
    semctl(sem_id, MUTEX2, IPC_RMID, 0);
    exit(0);
  }

  return 0;
}

ecco l'output:

Codice: Seleziona tutto

Father final: CHé SCHIAVA DI ROMAIDDIO LA CREò.
Father final: CHé SCHIAVA DI ROMAIDDIO LA CREò.
Father final: CHé SCHIAVA DI ROMAIDDIO LA CREò.
Father final: CHé SCHIAVA DI ROMAIDDIO LA CREò.
Father final: CHé SCHIAVA DI ROMAIDDIO LA CREò.
Father final: CHé SCHIAVA DI ROMAIDDIO LA CREò.
Father final: CHé SCHIAVA DI ROMAIDDIO LA CREò.
Ricevo queste in loop, devo terminare l'esecuzione del terminale per chiudere tutto.
Qualcuno potrebbe dirmi dove sbaglio ? :muro: :muro: :muro: :muro: :muro:
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 15 ospiti