Semafori con priorità in C

di il
2 risposte

Semafori con priorità in C

Ciao, sono alle prese con un esercizio dove devo creare N processi con due diverse priorità(alta e bassa) che condividono K risorse equivalenti. I processi che utilizzano le risorse dovranno iniziare i rispettivi cicli di esecuzione tutti assieme. Ciascun processo ripete l'accesso ad una risorsa per N volte e per scegliere quale processo attivare tra quelli sospesi devo dare precedenza a quelli con priorità maggiore.
io ho scritto questo codice:

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

#define K 5		/*numero massimo di risorse disponibili */
#define NUM_ITE 3	/*numero di iterazioni nella funzione usaRisorse*/
#define N1 4		/*processi di tipo A (priorità alta) */
#define N2 6		/*processi di tipo B (priorità bassa) */
#define N N1+N2		/*processi totali */
#define ritardo 3	

typedef struct risorse{
	int num_libere;		//numero risorse utilizzabili
	int disp[K];		//numero risorse disponibili
	int sospesi[2];		//priorità (1)= alta, priorità(0)= bassa
}Risorse;

/*Dichiarazione variabili globali e condivise */

int shmid;
int mutex, semris,semprint;
Risorse *R;

/*variabili per la sospensione*/
int priv[2];		/*semaforo privato con priorità [prio] */

/*Funzione di inizializzazione dei campi della struttura risorse e dei semafori*/
void init(){
  int i; 
  for(i=0;i<K;i++){
	  R->disp[i]=1;	//tutte le risorse disponibili
	}
  R->num_libere= K;			//tutte le risorse libere
  R->sospesi[1]=R->sospesi[0]=0;	//nessun processo sospeso
  seminit(mutex, 0, 1); 
  seminit(semris, 0, K);
  seminit(semprint, 0, 1);
  seminit(priv[0],0,N1);
  seminit(priv[1],0,N2);
}

// Funzione di stampa per la struttura Risorse
void printstatoris(){
  printf("S--> Numero di risorse: %d\n", R->num_libere);
  printf("S--> Numero di processi bloccati di priorità alta: %d\n", R->sospesi[1]);
  printf("S--> Numero di processi bloccati di priorità bassa: %d\n",R->sospesi[0]);
}

int Cerca_Risorsa(){
  int i=0;
  int trovata=-1;
  while ((i<K) && (trovata==-1)){			//esegue il ciclo finchè ci sono risose da controllare e non è stata trovata nessuna risorsa
    if (R->disp[i]==1){				//se risorsa libera
      trovata=i;					
      R->disp[i]=0;				//risorsa impostata come occupata
    }
    i++;
  }
  return trovata;
}

// Funzione di acquisizione delle risorse
int Acquisisci(int priorita){
    int id_risorsa;
    down(mutex,0);
    id_risorsa=Cerca_Risorsa(R);
    if(id_risorsa==-1){					//nessuna risorsa disponibile
      R->sospesi[priorita]++;
      down(semprint,0);
      printf("W--> Richiesta pendente del processo di priorità %d : %d che vuole ottenere una risorsa\n",priorita, getpid());
      up(semprint, 0);
      up(mutex, 0);
      down(priv[priorita], 0);
      down(mutex,0);
      R->sospesi[priorita]--;
      id_risorsa=Cerca_Risorsa();
      up(mutex, 0);
      down(semprint, 0);
      printf("A-->Il processo di priorità %d con pid %d in attesa acquisisce la risorsa\n",priorita, getpid());
      printstatoris();
      up(semprint, 0);
    }
    down(semris, 0);
    R->num_libere = R->num_libere--;
    up(mutex, 0);
    printf("stampa %d\n",id_risorsa);
    return id_risorsa;
  }

// Funzione di rilascio delle risorse
void Rilascia(int Res_id){
  int j;
  up(semris, 0);
  down(mutex, 0);
  R->disp[Res_id]=1;				//rilascio risorsa impostandola a 1(libera)
  R->num_libere = R->num_libere++;
  down(semprint, 0);
  printf("R--> Il processo con pid %d rilascia la risorsa...\n",getpid());
  printstatoris(R);
  up(semprint, 0);
  if(R->sospesi[1]>0)
    up(priv[1],0);
  else if(R->sospesi[0]>0)
    up(priv[0],0);
  else
    up(mutex,0);
}

// Funzione per l'esecuzione di NUM_ITE delle funzioni Acquisisci e Rilascia, ritardate nel mezzo dalla chiamata di sistema sleep()
void UsaRisorsa(int priorita){
  int i;
  int Res_id;
  for(i=0; i<NUM_ITE;i++){
    Res_id=Acquisisci(priorita);
    printf("valore %d\n", semprint);
     waitz(semris,0);						//attendo che tutti i processi che utilizzano una risorsa inizino insieme
    sleep(ritardo);
    Rilascia(Res_id);
  }
}
main(){
	int n,i;
	int p1=1;
	int p0=1;
	if ((shmid = shmget(IPC_PRIVATE,sizeof(Risorse),0600)) == -1) perror("Creazione memoria condivisa");
	if ((semris = semget(IPC_PRIVATE,1,0600)) == -1) perror("Creazione semaforo semris");
	if ((priv[0] = semget(IPC_PRIVATE,1,0600)) == -1) perror("Creazione semaforo privato priorità bassa");
	if ((priv[1] = semget(IPC_PRIVATE,1,0600)) == -1) perror("Creazione semaforo privato priorità alta"); 
	if ((mutex = semget(IPC_PRIVATE,1,0600))==-1)perror("Creazione semaforo mutex");
	if ((semprint = semget(IPC_PRIVATE,1,0600))==-1)perror("Creazione semaforo semprint");
	R = (Risorse*) shmat(shmid, NULL, 0);
	init();
	printf("Risorse iniziali disponibili: %d\n", R->num_libere);
	while ((p1+p0)<N){
	  if(p1<=N1){
	    if (fork()==0){
	      UsaRisorsa(1);	//priorità alta
	      p1++;
	      exit(0);
	    }
	  }
	  if(p0<=N2){
	    if (fork()==0){
	      UsaRisorsa(0);	//priorità bassa
	      p0++;
	      exit(0);
	    }
	  }
	}
	for(i=0;i<N1;i++){
	  n=wait(0);
	  down(semprint, 0);
	  printf("Terminato processo %d\n",n);
	  up(semprint, 0);
	}
	for(i=0;i<N2;i++){
	  n=wait(0);
	  down(semprint, 0);
	  printf("Terminato processo %d\n",n);
	  up(semprint, 0);
	}
  printf("Risorse finali disponibili: %d\n", R->num_libere);
  if(semctl(semris,0,IPC_RMID)==-1) perror("Rimozione semaforo semris");
  if(semctl(priv[0],0,IPC_RMID)==-1) perror("Rimozione semaforo privato");
  if(semctl(priv[1],0,IPC_RMID)==-1) perror("Rimozione semaforo privato");
  if(semctl(mutex,0,IPC_RMID)==-1) perror("Rimozione semaforo mutex");
  if(semctl(semprint,0,IPC_RMID)==-1) perror("Rimozione semaforo semprint");
  if(shmctl(shmid,IPC_RMID,NULL)==-1) perror("Rimozione memoria condivisa");
}
Il file collegato con le funzioni richiamate è il seguente:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int waitz(int semid, int semnum)
        /* attesa del valore zero sulla componente semnum di semid */
{
  int r;
  struct sembuf sb;
  sb.sem_num=semnum;
  sb.sem_op=0;
  sb.sem_flg=0;
  r=semop(semid,&sb,1);
  if (r==-1) perror("semop in attesa");
  return r;
}


int down(int semid, int semnum)	
	/* operazione DOWN sulla componente semnum di semid */
{
  int r;
  struct sembuf sb;

  sb.sem_num=semnum;
  sb.sem_op=-1;
  sb.sem_flg=0;
  r=semop(semid,&sb,1);
  if (r==-1) perror("semop in down");
  return r;
}

int up(int semid, int semnum)	
	/* operazione UP sulla componente semnum di semid */
{
  int r;
  struct sembuf sb;

  sb.sem_num=semnum;
  sb.sem_op=1;
  sb.sem_flg=0;
  r=semop(semid,&sb,1);
  if (r==-1) perror("semop in up");
  return r;
}

int seminit(int semid, int semnum, int initval)
	/* inizializzazione con initval della componente semnum di semid */
{
  int r;
 
  #if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
  /* union semun is defined by including <sys/sem.h> */
  #else
  /* according to X/OPEN we have to define it ourselves */
  union semun {
        int val;                  /* value for SETVAL */
        struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
        unsigned short *array;    /* array for GETALL, SETALL */
                                  /* Linux specific part: */
        struct seminfo *__buf;    /* buffer for IPC_INFO */
  };
  #endif

  union semun arg;

  arg.val=initval;
  r=semctl(semid,semnum,SETVAL,arg);
  if (r==-1) perror("semop in up");
  return r;
}
Non capisco cosa continuo a sbagliare, mi va sempre in loop. Se riuscite ad aiutarmi...
Grazie!!!!!

2 Risposte

  • Re: Semafori con priorità in C

    Prova a descrivere, a parole, quale e' la soluzione che volevi implementare.

    Poi si puo' confrontare il codice con la soluzione ideata
  • Re: Semafori con priorità in C

    Provo a spiegare un po’…
    Nel main creo i semafori e le strutture dati che mi servono per il programma e li inizializzo con la funzione prima dichiarata init():
    mutex serve per sincronizzare l’accesso alla sezione critica dove quindi utilizzo variabili condivise (inizializzato a 1);
    semris serve per sincronizzare le risorse, non utilizzare più risorse di quelle disponibili (inizializzato a K, cioè 5 risorse)
    semprint serve per sincronizzare la stampa delle variabili condivise (inizializzato a 1)
    priv[0] e priv[1] servono per sincronizzare i processi di priorità alta e bassa (inizializzati a N1=4,N2=6), usate per la sospensione di questi processi.
    Nella struttura risorse uso l'array di interi disp[K] inizializzato a 1 cioè tutte le risorse disponibili e sospesi[2] che serve per contare i processi sospesi con priorità alta e bassa.
    Con un ciclo While inizio l’acquisizione delle risorse fino a quando non arrivo a N cioè che tutti i processi sono stati eseguiti. P1 e P0 servono per contare i processi che hanno utilizzato la risorse con priorità alta e bassa.
    La funzione UsaRisorsa viene richiamata dal main e crea un ciclo, di 3 ripetizioni(numero di volte che viene acquisita una risorsa da ciascun processo),
    Nella funzione acquisisci cerco una risorsa libera(usando la funzione Cerca_risorsa che cerca tra tutte le risorse una con valore 1, cioè libera e se la trova la imposta a 0 e restituisce l’ID). Se ho ricevuto un numero diverso da -1 , cioè se ha trovato una risorsa allora diminuisco le risorse libere e stampo l’ID, altrimenti la sospendo in attesa che qualcuno rilasci la sua risorsa.
    Nella funzione Rilascia imposto l’ID della risorsa che era occupata ad 1(rendendola quindi libera) e cerco tra i processi sospesi se ce ne è uno con priorità alta allora lo riattivo, altrimenti risveglio uno con priorità bassa o se non c’è nessuno aumento il semaforo mutex e non faccio nient’altro.

    Non so se sono riuscito a far capire la soluzione che ho usato...
Devi accedere o registrarti per scrivere nel forum
2 risposte