Problema con gestione dei processi

di il
14 risposte

Problema con gestione dei processi

Salve a tutti sono nuovo del forum e ho un problema con un programma per la gestione di processi.
Il programma che devo fare richiede in ingresso un numero N di argomenti compresi tra 3 e 10 e il valore di ogni argomento deve essere contenuto tra 1 e 4.
Il processo padre dovrà creare N processi figli ognuno dei quali dovrà aspettare un numero casuale di tempo compreso tra 1 e 5 secondi stamperanno un messaggio e terminano.
Ad ogni processo figlio sarà assegnato un argomento che è stato passato inizialmente e ogni volta che un processo figlio sarà terminato il processo padre dovrà decrementare il valore corrispondente al processo figlio terminato.
Se il valore decrementato è maggiore o uguale di 1 dovrà creare un nuovo processo figlio con le caratteristiche menzionate precedentemente altrimenti se è uguale a zero il processo padre dovrà creare un figlio che esegue un programma /usr/bin/xmessage con argomento il figlio e termina.
Il programma padre terminerà quando quanto tutti i figli sono terminati o che non è possibile creare altri processi (i valori N relativi a ciascun figlio sono uguali a: -1)

Ho fatto un abbozzo di codice vi volevo chiedere se potevate darmi una mano dato che sto imparando ora a programmare grazie in anticipo(non è concluso manca la stampa a video finale del padre)

#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>

int main(int argc,char *argv[])
{
	int status,pid,i,t,a;
	if(argc < 5 || argc > 11)
	{
		printf("Numero di argomenti errato\n");
		exit(-1);
	}
	
	for(i=1;i<=argc;i++)
	{
		if((a=atoi(argv[i]))<1 || (a=atoi(argv[i]))>4)
		{
			printf("Errore valore argomenti\n");
			exit(-2);
		}
	}

	for(i=1;i<=argc;i++)
	{
		if((pid=fork())==0)
		{      
			int N=atoi(argv[i]);
			srand(time(NULL));
			t = rand() % 5 + 1;
			sleep(t);
			exit(N);
		}
		else
		{
			wait(&status);
			status=status-1;
			if(status>=1)
			{
				if((pid=fork())==0)
				{
					srand(time(NULL));
					t = rand() % 5 + 1;
					sleep(t);
					exit(status);
				}
			}
			if(status==0)
			{
				if((pid=fork())==0)
				{
					execvp("/usr/bin/xmessage",getpid());
					exit(0);
				}
			}
			else
				exit(-3);		 
		}
	}	
	return 0;
}

14 Risposte

  • Re: Problema con gestione dei processi

    Nessuno mi può dare una mano?
  • Re: Problema con gestione dei processi

    Devi aspettare ixamit, lui sa la gestione dei processi su linux.
  • Re: Problema con gestione dei processi

    Grazie mille aspetto
  • Re: Problema con gestione dei processi

    Ciao,
    ho dato un'occhio al tuo codice:
    1) inizio del main sul check di argc
    2) nel parent, lo status della wait restituisce il valore shiftato di 8 bit, per leggere il valore reale protresti usare la macro WEXITSTATUS

    Domanda.... nel testo non è specificato che il genitore debba attendere la morte del figlio con la wait.
    Se è corretto i valore devono esser letti inizialmente da argv, per cui un array di appoggio e da li le operazioni di sottrazione del valore.
    Se non devi attendere, allora sarebbe il caso di usare un struttura che contenga almeno il pid ed il valore e sarà anche necessaria la getpid (unistd.h).
  • Re: Problema con gestione dei processi

    Il padre deve sempre aspettare la terminazione di qualsiasi processo figlio e in base a quale processo figlio è terminato dovrà decrementare il valore di n corrispondente a quel figlio(i valori di n erano in argv[]) e poi controlla il valore decrementato se è maggiore o uguale di 1 etc etc....Potresti dirmi come utilizzare wexitstatus e come utilizzare l'arraydi appoggio in questione? Scusa ma sono un pò niubbo in queste cose grazie ancora ciao!
  • Re: Problema con gestione dei processi

    Potresti dirmi come utilizzare wexitstatus
    value=WEXITSTATUS(status);
    come utilizzare l'array di appoggio in questione
    prima di iniziare il giro di fork devi copiare i valori letti da argv su un array perchè quando sei nel child non puoi sapere il valore attuale ...se non inizialmente. Cioè dovresti riscrivere su argv ... no?!
    Per cui dopo aver fatto le tue verifiche di sui parametri (ti ricordo che devi correggerle perchè sono sbagliate) devi crearti quest'array di comodo con dentro i valori interi di argv. Guarda che mi sto divulgando su un semplice array di int.

    Devi girare (iterare) per il numero di elementi dell'array, fai la fork (come hai già fatto) swith sul pid restituito dalla fork. case -1 la fork non ha funzionato esci con un valore negativo (-1 può andare bene), case 0 sei nel child e qui devi fare come hai già fatto facendo un exit sull'elemento dell'array che stai trattando... ahhh una cosa molto importante: facciamo fare al child anche l'esecuzione del binario utilizzando una variabile boleana aggiuntiva; questo perchè utilizzeremo sempre lo stesso fork gia presente senza crearne ulteriori. case parent wait va bene + macro WEXITSTATUS - 1 e andiamo a memorizzarlo nel nostro array. Ora fai i controlli : se maggiore prosegui con l'elemento successivo se uguale setta la variabile boleana a TRUE , se minore di -1 è un errore di fork, se -1 setto la bool a FALSE. FINITO!
  • Re: Problema con gestione dei processi

    Ho cannato nel check!
    ...Ora fai i controlli : se maggiore prosegui con l'elemento successivo...
    Se maggiore fare niente in quanto il valore è già decrementato. Rimani sullo stesso vettore
  • Re: Problema con gestione dei processi

    Ho messo giu un bozzetto e l'ho provato. Questo è l'out:
    
    max@studio:~> ./a.out      
    child #13328     ---> sleeping for 5 seconds
    parent#13327     ---> get value=2 (status=768)
    child #13329     ---> sleeping for 5 seconds
    parent#13327     ---> get value=1 (status=512)
    child #13330     ---> sleeping for 1 seconds
    parent#13327     ---> get value=0 (status=256)
    child #13331     ---> exec xmessage
    parent#13327     ---> get value=-1 (status=0)
    child #13332     ---> sleeping for 4 seconds
    parent#13327     ---> get value=3 (status=1024)
    child #13333     ---> sleeping for 1 seconds
    parent#13327     ---> get value=2 (status=768)
    child #13334     ---> sleeping for 2 seconds
    parent#13327     ---> get value=1 (status=512)
    child #13358     ---> sleeping for 3 seconds
    parent#13327     ---> get value=0 (status=256)
    child #13359     ---> exec xmessage
    parent#13327     ---> get value=-1 (status=0)
    child #13360     ---> sleeping for 4 seconds
    parent#13327     ---> get value=2 (status=768)
    child #13369     ---> sleeping for 4 seconds
    parent#13327     ---> get value=1 (status=512)
    child #13371     ---> sleeping for 5 seconds
    parent#13327     ---> get value=0 (status=256)
    child #13372     ---> exec xmessage
    parent#13327     ---> get value=-1 (status=0)
    max@studio:~>
    
    Però in effetti si potrebbe fare a meno dell'array passando solamente l'intero di start ad una funzione che itera sulla fork fino alla morte dell'ultimo child.
    Mi sono confuso inizialmente pensando alla non attesa di morte del singolo processo...
  • Re: Problema con gestione dei processi

    Innanzitutto ixamit grazie per l'aiuto che mi stai dando, volevo porti alcune domande:
    dato che devo aspettare i figli e quindi decrementare i relativi valori hai detto che non c'è bisogno di utilizzare l'array, adesso io mi chiedo come posso assegnare gli argomenti ai relativo figlii? (dovrebbe essere argv[1] al figlio 1, argv[2] al figlio 2 e così via,argv[0] non lo considero perchè è il primo comando che non considero argomento....) Come ho assegnato io i valori ad ogni singolo figlio penso che sia sbagliato....come lo devo modificare il codice che ho fatto io sempre che non sia completamente sbagliato? Scusami ma sono un pò duro di comprendorio . Il concetto è che non riesco a tradurre in codice il fatto che ad ogni processo figlio dare un argomento in ordine di creazione.....
  • Re: Problema con gestione dei processi

    Per far meno confusione consiglio di eseguire una funzione (la chiamo subfork) alla quale passo il valore iniziale di argv[1]...argv[n]. A questo punto la nostra subfork itera dal valore iniziale.
    Pseudo codice:
    
      ...
      for (;;)
      {
        pid=fork();
        switch (pid)
        {
          case -1:
            qui devo uscire con un errore
            exit  (-1);
          case 0:
            SONO IL CHILD
            se il mio BOOL==TRUE
            {
                eseguo il mio xmessage con il getpid
                exit (0)
            }
            mi addormento un pò per un tempo rnd da 1 a 5 secs
            exit (value);
          default:
            SONO IL PARENT
            eseguo la wait con status
            utilizzo la macro WEXITSTATUS per shiftare di 8 bit assegnandolo a value
            se (value > 0)
            {
              decremento value 
              se value = 0 setto il mio BOOL = TRUE
            }
            anche  se (value <0)
              return (value) <---- ok questo è l'eventuale errore intercettato
            anche
              return 0         <----- nessun errore posso tornare al main
        }
    ...
    
    Ok. Qui termina il mio aiuto.

    Saluti
    Max
  • Re: Problema con gestione dei processi

    Ragazzi ci sono riuscito ora funziona tutto l'unico problema è che non fa la execv e non ho capito come mai potreste darmi una mano?
    
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc,char *argv[])
    {
    	int status,i,pid,t,value;
    	int vett[argc-1];
    	int v=0;
    	char h[64];
    	
    	if(argc < 4 || argc > 11)
    	{
    		printf("errore numero argomenti\n");
    		exit(-1);
    	}
    
    	for(i=1;i<argc;i++)
    	{
    		if((strtol(argv[i],NULL,0))<1 || ((strtol(argv[i],NULL,0))>4))
    		{printf("valore argomenti errato\n");
    		exit(-2);}
    	}
    	
    	for(i=1;i<argc;i++)
    	{
    		vett[v]=strtol(argv[i],NULL,0);
    		v++;
    	}
    	argc--;
    
    	for(i=0;i<argc;i++)
    	{	
    		if((pid=fork())==0)
    		{	
    		 	srand(time(NULL));
    			t = rand() % 5 + 1;
    			sleep(t);
                            printf("Sono il processo figlio %d ho aspettato %d secondi e termino\n",getpid(),t);
    			exit(vett[i]);}
    		
    		
    		
    	}
    	
    	for(i=0;i<argc;i++)
    	{                   wait(&status);
    			    value=WEXITSTATUS(status)-1;
       		            vett[i]=value;
    	}
    		
    	
    		for(i=0;i<argc;i++)
    		{      
    			while(vett[i]>=0)	
    			{	if(vett[i]>0)
    				{	pid=fork();
    					if(pid==-1)
    					{perror("errore fork ");
    				 	exit(-1);}
    				 
    					if(pid==0)
                                     	{srand(time(NULL));
    			         	t = rand() % 5 + 1;
    			         	sleep(t);
                                     	printf("Sono il processo figlio %d ho aspettato %d secondi e termino\n",getpid(),t);
    				 	exit(0);}
           				
    				
    
    				}
                        		
    				if(vett[i]==0)
    				{	pid=fork();
    				 	if(pid==-1)
    				 	{perror("errore fork ");
    				  	exit(-1);}
    				 
    				
    				 	if(pid==0)															
    					{	
    	                                	sprintf(h,"Il processo figlio %d è terminato\n",getpid());					
    				        	execv("usr/bin/xmessage",h);
                			        	exit(-1);
    					}
    				 	
    				
    				
    				}
    		
    			wait(&status);
    			--vett[i];
    			}
    		}
    			
    		        
    			printf("Sono il padre %d e termino perchè non è possibile creare altri processi\nin quanto il valore deglim argomenti è: \n",getpid());
    			for(i=0;i<argc;i++)
    			printf("%d ",vett[i]);
    			printf("\ne tutti i figli sono terminati\n");			
    			return 0;
    		
    }
    
  • Re: Problema con gestione dei processi

    Up nessuno sa darmi una mano sulla execv???
  • Re: Problema con gestione dei processi

    Usa google e in mancanza di internet digita: man execv
    
    int execv(const char *pathname, char *const argv[]);
    
    dove pathname è tutto il percorso compreso il nome
    argv[0]=nome binario
    argv[n]=args
    argv[n+1]=(char *) 0
    
  • Re: Problema con gestione dei processi

    Visto che l'hai terminato e che mi sembra tu volessi far partire tutti i processi insieme (non è mai garantito comunque), ti faccio vedere come l'avrei fatto io senza l'array tanto menzionato di appoggio ma solo usando exit e WEXITSTATUS. Lo stesso esercizio può esser fatto usando i segnali o comunicando via pipe... ma questa è un'altra storia
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    void execbin ()
    {
      char *arg[3],spid[6];
      int pid;
      
      if (pid=fork()==0)
      {
        snprintf (spid,sizeof(spid),"%d",getpid());
        arg[0]="xmessage";
        arg[1]=spid;
        arg[2]=(char *)0;
      
        execv ("/usr/bin/xmessage",arg);
      }
      else
        exit (pid);
    }
    
    void subfork (int value)
    {
      int pid,t;
      pid=fork();
      if (pid<0)
      {
        fprintf (stderr,"ops, cannot fork\n");
        exit (pid);
      }
      else if(pid==0)
      { 
        if (value==0)
          execbin ();
        else
        {
          srand(time(NULL));
          t = rand() % 5 + 1;
          fprintf(stdout,"child#%d waiting %d seconds && exit(%d)\n",getpid(),t,value);
          sleep(t);
        }
        exit(value);
      }
    }
    
    int main(int argc,char *argv[])
    {
      int pid,n,status,value,i;
      int parent=getpid();
    
      n=argc-1;
      if (n<3 || n>10)
      {
        fprintf (stdout,"Gli argomenti devono essere compresi tra 3 e 10. Tu hai messo %d argoment%c.\n",n,(n==1)?'o':'i');
        return -1;
      }
      for (i=0;i<n;i++)
      {
        if (atoi(argv[i+1])<1 || atoi(argv[i+1])>4)
        {
          fprintf (stdout,"I valori devono essere compresi tra 1 e 4. Tu hai messo %s nel %d parametro.\n",argv[i+1],i+1);
          return -1;
        }
      }
                 
      for (i=0;i<n;i++)
        subfork (atoi(argv[i+1]));
    
      for (;parent==getpid() && n;)
      {                   
        pid=wait(&status);
        value=WEXITSTATUS(status);
        value=(value>128) ? value-256 : value;
        
        fprintf (stdout,"parent get form child#%d=%d\n",pid,value);
        if (value>0)
          subfork (value-1);
        else
          n--;
      }
      fprintf (stdout,"DONE\n");
      
      return 0;
    
    }
    
Devi accedere o registrarti per scrivere nel forum
14 risposte