System Calls - write() read () int

di il
2 risposte

System Calls - write() read () int

Ciao a tutti
Sono nuovo del forum, e mi sono iscritto dopo un'intera giornata passata a cercare di capire come scrivere un int su file utilizzando le System Call write e read.

vi posto il codice, comprensivo di traccia:
/* Scrivere un programma C in cui un processo crea un file nipoti.txt e vi
scrive un intero n. A questo punto il processo attiva un processo figlio
che legge dal file n e crea a sua volta n figli e ne attende la
terminazione (di tutti). */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main() {
   /* Variabili da utilizzare */
   int n, pid, fd, status;
   int i, buf;

   n = 5;

   /* il processo crea il file. In questo modo il file sarà disponibile
   per tutti i figli, a patto che non vengano eseguiti Context-Switch */
   fd = open("./nipoti.txt", O_CREAT | O_RDWR | O_TRUNC, 0777);
   
   /* Viene quindi scritto il numero di processi da creare.
   N.B. la traccia chiede solamente di scrivere un numero, quindi in questo
   caso mi sono preso la libertà di definirlo direttamente nel codice */
   buf = write(fd, &n, sizeof(n));
   
   /* poniamo n = 0 solo per assicurarci che il suo valore iniziale 5
   non venga successivamente utlizzato. il suo valore deve essere
   infatti letto dal file nipoti.txt */
   n = 0;
   
   /* Quindi si crea il Figlio */
   pid = fork();
   
   /* Si controlla che tutto sia andato secondo i piani */
   if(pid < 0)
      printf("Errore durante la creazione del processo figlio\n");
   else if(pid == 0) { /* eseguito dal figlio */
      printf("Figlio(%d) con padre(%d) creato!\n",getpid(), getppid());
      
      read(fd, &n, buf);
      printf("DEBUG: n vale %d \n", n);
      printf("DEBUG: buf vale %d \n", buf);

      if(n <= 0) {
         printf("Bisogna specificare un numero > 0\n");
         return 1;
      }

      for(i = 0; i < n; i++) {
         /* Ora creiamo i nipoti */
         pid = fork();
         
         if(pid < 0)
            printf("Errore durante la creazione del processo nipote\n");
         else if(pid == 0) {
            printf("Nipote(%d) con padre(%d) creato!\n",getpid(),getppid());
            i = n;
         }
      }
      
      if(pid > 0) { /* viene eseguito dal figlio */
         for(i = 0; i < n; i++) {
         /* Ora creiamo i nipoti */
         pid = wait(&status);
         
         if(pid > 0)
            printf("Nipote(%d) terminato!\n", pid);
         }
      }  
   } else { /* eseguito dal padre */
      pid = waitpid(pid, &status, 0);
      
      if(pid > 0)
         printf("Figlio(%d) terminato!\n", pid);
   }

   close(fd);
   return 0;
}
anche se non c'è scritto, non posso usare altro, se non che le system call write e read.
e purtroppo (Se provate a compilarlo ed eseguirlo ve ne accorgerete) il programma così come l'ho scritto non funziona.

Viene creato il file, ma al suo interno viene scritta la rappresentazione ascii di 5, viene quindi generato il figlio che prova a leggere il numero dal file.. ma non lo trova, quindi ritorna l'errore.

ho anche provato a scrivere direttamente sul file 5 e a saltare la parte del write nel programma, per vedere se almeno la read leggeva correttamente 5 e poi lo salvava nell'intero.. ma putroppo ciò non succede..

quindi sono in una situazione di stallo totale
spero che qualcuno possa aiutarmi,
easly

2 Risposte

  • Re: System Calls - write() read () int

    Ciao!! Allora fai un po di confusione forse sulla read e la write:P
    Sono funzioni che lavorano a basso livello...scrivono e leggono file binari!
    quando dici ho provato a scrivere in un file il valore 5 e a leggerlo con la read ...non accade cio' che pensi!...ovvero il 5 letto dalla read non viene interpretato come il valore 5 che hai digitato e di
    conseguenza all'indirizzo &n viene fornito un altro valore!

    Inoltre bisogna comprendere bene i parametri da passare alle due funzioni!
    il terzo parametro rappresenta il numero di byte che vengono scritti e letti.. nella write utilizzi n
    che potrebbe anche andare ma visto che sai che n e' un tipo int sarebbe meglio mettere sizeof(int)..
    nella read invece scrivere buf e' un errore...ci vanno sempre il numero di byte che vai a leggere
    quindi sizeof(int) perche' sai che devi leggere un valore int dal file!

    write(fd, &n, sizeof(n));
    read(fd, &n, buf);

    ti consiglio sempre di utilizzare due interi in cui salvare i valori ritornati dalle due funzioni per
    controllare che la lettura e scrittura siano andate a buon fine e che non ci siano stati problemi...!
    Poi quando crei il file e scrivi il valore devi chiuderlo prima di leggerlo...per salvare le modifiche apportate!...poi il file sara' pronto per essere letto!
    Devi includere anche <sys/wait.h> per la wait e la waitpid.

    Qui ti posto il codice ...ho aggiunto qualke controllo in piu'!
    
    /* Scrivere un programma C in cui un processo crea un file nipoti.txt e vi
    scrive un intero n. A questo punto il processo attiva un processo figlio
    che legge dal file n e crea a sua volta n figli e ne attende la
    terminazione (di tutti). */
    
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h> 
    #include <sys/wait.h>   // per la waitpid
    #include<stdlib.h> // per la exit
    
    int main() {
       /* Variabili da utilizzare */
       int n, pid, fd, statusN, statusF, i, waitVn, waitVf, nwrite, nread;
       // nwrite e nread numero elementi effettivamente scritti/letti da write/read
       // waitVn per la wait nipoti, waitVf per la wait figlio 
       int pidN; // riferito ai nipoti ..ma va bene anche usare sempre pid
       n = 5;
    
      /* il processo crea il file. In questo modo il file sarà disponibile
       per tutti i figli, a patto che non vengano eseguiti Context-Switch */
       fd = open("./nipoti", O_CREAT | O_RDWR | O_TRUNC, 0777);
       
       if(fd < 0)
       {
         perror("\nUnable Create File..");
         exit(EXIT_FAILURE);
    
       }
       /* Viene quindi scritto il numero di processi da creare.
       N.B. la traccia chiede solamente di scrivere un numero, quindi in questo
       caso mi sono preso la libertà di definirlo direttamente nel codice */
    
       nwrite = write(fd, &n, sizeof(int));
       if(nwrite < 0)
       {
         printf("\nProblemi con la write..");
         exit(EXIT_FAILURE);
       }
       
       close(fd); //chiudo il file appena creato
     
       
       /* poniamo n = 0 solo per assicurarci che il suo valore iniziale 5
       non venga successivamente utlizzato. il suo valore deve essere
       infatti letto dal file nipoti.txt */
       n = 0;
       
       /* Quindi si crea il Figlio */
       pid = fork();
       
      
       /* Si controlla che tutto sia andato secondo i piani */
       if(pid < 0)
       {
         perror("\nUnable To Fork!"); // stampa anche il valore della variabile errno
         exit(EXIT_FAILURE);
       }
       else if(pid == 0) 
            { /* eseguito dal figlio */
          
             int md;
             md = open("./nipoti", O_RDONLY);
             
             if(md < 0)
             {
              printf("\nImpossibile aprire il file...");
              exit(EXIT_FAILURE); 
             }
             printf("\n\nFiglio(%d) con padre(%d) creato!\n",getpid(), getppid());
         
             nread = read(md, &n, sizeof(int));   /// il terzo parametro deve indicare i byte letti!
             if(nread < 0)
             {
              printf("\nErrore nella read");
              exit(EXIT_FAILURE);
             }
             
             close(md); // chiudo il file non serve piu'
             printf("(DEBUG: n vale %d)\n", n);
      
             //controllo valore n
             if(n <= 0) 
             {
             printf("Bisogna specificare un numero > 0\n");
             exit(EXIT_FAILURE);
             }
        
             printf("\nCREO I NIPOTI....\n");
            
             for(i = 0; i < n; i++) 
             {
                /* Ora creiamo i nipoti */
                pidN = fork();
             
             
                if(pidN== 0) 
                {
                  printf("\nNipote(%d) con padre(%d) creato!\n",getpid(),getppid());
                  i = n;
                }else if( pidN < 0)
                {
                  perror("\nUnable To Fork (nipote)");
                  exit(EXIT_FAILURE);
                }
     
              
              }//fine for nipoti
              /* il figlio attende che i nipoti termino*/
              for(i=0; i< n; i++)
              {
                   waitVn = wait(&statusN);
                   if(waitVn > 0)
                   printf("\n--Nipote(%d) terminato!--\n", waitVn); 
      
                
              }//fine for attesa nipoti    */
    
          } if(pid> 0){ /* eseguito dal padre */
          
                waitVf = waitpid(pid, &statusF, 0);
         
                if(waitVf > 0)
                printf("*****Figlio(%d) terminato!*****\n", pid);
          }//fine else
    
       
       return 0;
    }
    
    
  • Re: System Calls - write() read () int

    Ciao e grazie per la risposta

    allora, non so se in ambiente linux sia diverso che altrove cmq io uso gcc per compilare
    e la compilazione va a buon, così come l'esecuzione del programma (Anche senza le librerie sys/wait.h)

    detto questo, write e read, almeno da quello che ho imparato a lezione xD, ricevono come terzo paramentro il numero di bytes da scrivere e leggere (rispettivamente) e danno in uscita il numero di bytes effetivamente scritti/letti.

    quindi non è un errore inserire sizeof(n) (infatti anche mettendo sizeof(int) ricevo lo stesso risultato, ovvero 4).

    La difficoltà della prova risiede proprio nel fatto che bisogna scrivere un intero e non un carattere ascii avenente "la forma" di quell'intero

    ed infatti nel file viene scritta effettivamente la rappresentazione del intero.

    la cosa che effettivamente mi sfuggiva era il fatto che per poter leggere un file bisognava prima chiuderlo!

    e quando l'ho letto ho ricevuto l'illuminazione, ed ho subito provato ad usare lseek() per riposizionarmi all'inizio del file, et voilà il programma funziona:
    /* Scrivere un programma C in cui un processo crea un file nipoti.txt e vi
    scrive un intero n. A questo punto il processo attiva un processo figlio
    che legge dal file n e crea a sua volta n figli e ne attende la
    terminazione (di tutti). */
    
    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    
    int main() {
       /* Variabili da utilizzare */
       int n, pid, fd, status;
       int i, buf;
    
       n = 7;
    
       /* il processo crea il file. In questo modo il file sarà disponibile
       per tutti i figli, a patto che non vengano eseguiti Context-Switch */
       fd = open("./nipoti.txt", O_CREAT | O_RDWR | O_TRUNC, 0777);
       
       /* Viene quindi scritto il numero di processi da creare.
       N.B. la traccia chiede solamente di scrivere un numero, quindi in questo
       caso mi sono preso la libertà di definirlo direttamente nel codice */
       buf = write(fd, &n, sizeof(int));
       
       /* poniamo n = 0 solo per assicurarci che il suo valore iniziale 5
       non venga successivamente utlizzato. il suo valore deve essere
       infatti letto dal file nipoti.txt */
       n = 0;
       
       /* Quindi si crea il Figlio */
       pid = fork();
       
       /* Si controlla che tutto sia andato secondo i piani */
       if(pid < 0)
          printf("Errore durante la creazione del processo figlio\n");
       else if(pid == 0) { /* eseguito dal figlio */
          printf("Figlio(%d) con padre(%d) creato!\n",getpid(), getppid());
          
          /* Usiamo lseek per evitare di dover chiudere e riaprire il file
          impostando come punto di posizionamento l'inizio del file */
          lseek(fd, 0L, SEEK_SET);
          
          read(fd, &n, sizeof(int));
    
          if(n <= 0) {
             printf("Bisogna specificare un numero > 0\n");
             return 1;
          }
    
          for(i = 0; i < n; i++) {
             /* Ora creiamo i nipoti */
             pid = fork();
             
             if(pid < 0)
                printf("Errore durante la creazione del processo nipote\n");
             else if(pid == 0) {
                printf("Nipote(%d) con padre(%d) creato!\n",getpid(),getppid());
                i = n;
             } else /* eseguito dal figlio */
                /* rallentiamo l'esecuzione del figlio per essere sicuri
                che tutti i nipoti vengano creati prima di chiuderli */
                sleep(1); 
          }
          
          if(pid > 0) { /* viene eseguito dal figlio */
             for(i = 0; i < n; i++) {
             /* Ora creiamo i nipoti */
             pid = wait(&status);
             
             if(pid > 0)
                printf("Nipote(%d) terminato! (da %d)\n", pid, getpid());
             }
          }  
       } else { /* eseguito dal padre */
          pid = waitpid(pid, &status, 0);
          
          if(pid > 0)
             printf("Figlio(%d) terminato!\n", pid);
       }
    
       close(fd);
       return 0;
    }
    e funziona esattamente come dovrebbe.
    TI ringrazio ancora per l'aiuto, si può chiudere la discussione
Devi accedere o registrarti per scrivere nel forum
2 risposte