[C/C++] fork(), waitpid() und FileOperationen

Dieses Thema im Forum "Programmierung & Entwicklung" wurde erstellt von Smokers, 24. November 2010 .

  1. 24. November 2010
    fork(), waitpid() und FileOperationen

    Hallöchen,

    ich habe folgende drei Dateien (wobei ich bisher nur an dem main-Programm und am Child1 arbeite)

    main.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    
    #ifdef __unix__ || __Linux__
     #include <unistd.h>
     #include <sys/types.h>
     #include <sys/wait.h>
    #elif __MSDOS__ || __WIN32__ || _MSC_VER
     #include <io.h>
     #include <windows.h>
    
    
    int main(int argc, char *argv[]) {
     int fstatus =0;
     char filename[51];
     char key;
     int fp;
     pid_t pid1;
     pid_t pid2;
     int status1,status2;
     char *arguments[4];
     int i;
     
     if(argc < 2){
     while(strlen(filename) < 1){
     system("clear");
     printf("Bitte geben Sie eine Datei an!\n");
     scanf("%50s",&filename);
     fflush(stdin);
     }
     }
     else {
     strcpy(filename,argv[1]);
     }
     
     if( (fp = open(filename,O_RDONLY)) != -1){
     while(key != '1' && key != '2'){
     system("clear");
     printf("Datei schon vorhanden!Was soll getan werden?\n");
     printf("1) Überschreiben!\n");
     printf("2) Anhaengen!\n");
     key = getchar();
     fflush(stdin);
     }
     if(key == '1'){
     //printf("Überschreiben!\n");
     fp = open(filename,O_RDWR | O_TRUNC );
     }
     if(key == '2'){
     //printf("Anhängen!\n");
     fp = open(filename,O_RDWR | O_APPEND );
     }
     
     }
     else {
     //printf("Erstellen!\n");
     fp = open(filename,O_RDWR | O_CREAT ,0644);
     }
     
     
     char narg[10];
     sprintf(narg,"%d",fp);
     
     arguments[0] = argv[0];
     arguments[1] = narg;
     arguments[2] = filename;
     arguments[3] = NULL;
     
     
     pid1 = fork();
     if(pid1 == 0){
     execv("child1",arguments);
     }
    
     pid1 = waitpid(pid1,&status1,0);
     /*pid2 = fork();
     if(pid2 == 0) {
     execv("child2",arguments);
     }*/
     
     close(fp);
    }
    
    Child1.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    
    
    
    int main(int argc, char *argv[]) {
     int fp;
     char filename[51];
     char text[100];
    
     
     if(argc < 2){
     printf("Passed arguments are not enough");
     exit(1);
     }
     
     fp=atoi(argv[1]); 
     strcpy(filename,argv[2]);
     
     printf("Bitte geben Sie den Text ein!\n(Enter beendet die Eingabe)\n");
     
     scanf("%100s",&text);
     printf("text lautet:\n%s\n\nlaenge:%i\n",text,sizeof(text)-1);
     if( (write(fp,&text,sizeof(text))) == -1) {
     perror("write");
     }
    }
    
    Child2.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    
    
    
    int main(int argc, char *argv[]) {
     int fp;
     char filename[51];
     char buffer[100];
     if(argc < 2){
     printf("Passed arguments are not enough");
     exit(1);
     }
     fp=atoi(argv[1]); 
     strcpy(filename,argv[2]);
     
     
     printf("Datei '%s' wird ausgelesen!...\n\n");
     while((read(fp,&buffer,sizeof(buffer)) != 0)){
     printf("%s",buffer);
     }
    }
    



    Also wie man vllt sehen kann soll das Programm im main lediglich das File einlesen/erstellen falls nicht vorhanden oder übergeben...

    dann soll der Child1 das File beschreiben mit Text aus der CMD und child2 soll dann wiederum auslesen.

    Child1 und Child2 sollen mit execv ausgeführt werden wobei als Übergabeparameter a) das filename Pflicht ist und b) der FileDeskriptor



    Mein Problem ist das der erste Child Prozess den eingegebenen text nicht richtig schreibt, sobald ich die txt oder was auch immer, öffnen möchte mit gedit oder dergleichen, kommt der Fehler:

    "Die Auto-Text-Erkennnung konnte das File nicht erkennen ... bla bla bla"
    mit vi kommt dann ein etwas aussagekräftigerer Text :"Fehler in der letzten Zeile".


    Es muss irgendwie an write(fp,&text,sizeof(text)) liegen, denn wenn ich mal 4byte schreiben lassen, als fix Wert (also write(fp,&text,4) ) dann geht es und es befinden sich 4 buchstaben meines eingegebenen Textes in der Datei und sie lässt sich lesen.


    ich finde aber Partout den Fehler nun nicht

    Ich muss btw mit open(), close(),read() arbeiten weil ich sonst den FileDeskriptor nicht übergeben kann (arg[1]im child1)

    Danke schonmal im voraus.
     
  2. 24. November 2010
    AW: fork(), waitpid() und FileOperationen

    sizeof ist nur für den compiler und daher nicht geeignet für dein Anwendungsgebiet, nimm mal strlen zur Ermittlung der tatsächlichen Größe des eingegebenen Textes.
     
  3. 24. November 2010
    AW: fork(), waitpid() und FileOperationen

    Da hat N0S recht, sizeof gibt die Größe der Variable zurück, unabhängig vom Inhalt. Bei Arrays funktioniert das auch nur, wenn diese auf dem Stack angelegt werden.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    
    {
     char buf[100] = { "Hallo" };
     char *ptr = &buf[0];
    
     printf("sizeof(buf) = %d\n", sizeof(buf));
     printf("sizeof(ptr) = %d\n", sizeof(ptr));
    
     printf("strlen(buf) = %d\n", strlen(buf));
     printf("strlen(ptr) = %d\n", strlen(ptr));
    
     return 0;
    }
    Erzeugt folgende Ausgabe:
    Code:
    sizeof(buf) = 100
    sizeof(ptr) = 4
    strlen(buf) = 5
    strlen(ptr) = 5
    Wie du siehst, ist das nicht wirklich zuverlässig sizeof(buf) ergibt 100, weil buf nunmal 100 Bytes auf dem Stack belegt. sizeof(ptr) gibt nicht die Größe von buf zurück, sondern nur 4. Das liegt daran, dass ein Pointer genau 4 bytes auf dem Stack belegt

    Bei Strings also immer strlen() benutzen

    Gruß,
    pyro
     
  4. 26. November 2010
    AW: fork(), waitpid() und FileOperationen

    Oh man, ich glaub so richtig werd ich mit C nie warm.

    Vielen Dank für die Hilfe.

    Mein Programm ist nun soweit fertig

    -->
    main.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <fcntl.h>
    
    
    
    int main(int argc, char *argv[]) {
     int fstatus =0;
     char filename[51];
     char key;
     int fp;
     pid_t pid1;
     pid_t pid2;
     int status1,status2;
     char *arguments[4];
     int i;
     int erg1=0,erg2=0;
     
     if(argc < 2){
     while(strlen(filename) < 1){
     system("clear");
     printf("Bitte geben Sie eine Datei an!\n");
     scanf("%50s",&filename);
     fflush(stdin);
     }
     }
     else {
     strcpy(filename,argv[1]);
     }
     
     if( (fp = open(filename,O_RDONLY)) != -1){
     while(key != '1' && key != '2'){
     system("clear");
     printf("Datei schon vorhanden!Was soll getan werden?\n");
     printf("1) Ãœberschreiben!\n");
     printf("2) Anhaengen!\n");
     key = getchar();
     fflush(stdin);
     }
     if(key == '1'){
     //printf("Ãœberschreiben!\n");
     fp = open(filename,O_WRONLY | O_TRUNC );
     }
     if(key == '2'){
     //printf("Anhängen!\n");
     fp = open(filename,O_WRONLY | O_APPEND );
     }
     
     }
     else {
     //printf("Erstellen!\n");
     fp = open(filename,O_WRONLY | O_CREAT ,0644);
     }
     
     
     char narg[10];
     sprintf(narg,"%d",fp);
     
     arguments[0] = argv[0];
     arguments[1] = narg;
     arguments[2] = filename;
     arguments[3] = NULL;
     
     
     pid1 = fork();
     if(pid1 == 0){
     execv("child1",arguments);
     }
     
     pid1 = waitpid(pid1,&status1,0);
     close(fp);
     fp = open(filename,O_RDONLY);
     pid2 = fork();
     if(pid2 == 0) {
     execv("child2",arguments);
     }
     pid2 = waitpid(pid2,&status2,0);
    
     printf("\n");
     printf("Child 1 (%d) mit Status |%x|%x| beendet\n", pid1, (status1 >> 8)&0xFF, status1&0x7F);
     printf("Child 2 (%d) mit Status |%x|%x| beendet\n", pid2, (status2 >> 8)&0xFF, status2&0x7F);
     
     
     
     close(fp);
    }
    
    
    child1.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    
    
    
    
    int main(int argc, char *argv[]) {
     int fp;
     char filename[51];
     char text[501];
    
     
     if(argc < 2){
     printf("Passed arguments are not enough");
     exit(1);
     }
     
     fp=atoi(argv[1]); 
     strcpy(filename,argv[2]);
     system("clear");
     printf("Bitte geben Sie den Text ein!\n(Enter beendet die Eingabe)\n");
     
     fgets(text,sizeof(text),stdin);
     text[strlen(text)-1]='\0';
     
     if( (write(fp,&text,strlen(text))) == -1) {
     perror("write");
     }
    }
    
    child2.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <fcntl.h>
    
    #include <sys/stat.h>
    
    
    
    int main(int argc, char *argv[]) {
     int fp;
     char filename[51]; 
     fp=atoi(argv[1]);
     strcpy(filename,argv[2]);
     //char buffer[501];
     int test;
     lseek(fp,0,SEEK_SET);
     
     struct stat buf;
     
     fstat(fp,&buf);
     char buffer[buf.st_size];
     
     printf("Datei '%s' wird ausgelesen!...\n\n",filename);
     
     test = read(fp,buffer,buf.st_size);
     //test = read(fp,buffer,sizeof(buffer));
     //buffer[strlen(buffer)-1]='\0';
     fprintf(stdout,"%s",buffer);
     printf("\n");
    }
    


    Nun noch eine weiter letzte Frage die ungeklärt ist.
    Es kommt oft vor, das wenn ich längere Zeichenketten eingebe/das File erweitere nahezu zufällig, noch andere Zeichen in der Konsole ausgegeben werden.
    Es scheint mir als wäre es wahlloser Speicherinhalt.

    Findet jemand von euch die Stelle an der ich da unsauber gearbeitet hab oder der Fehler kommen kann? (eigentlich kanns ja nur beim einlesen(child1) oder ausgeben(child2) passieren)

    Sollte ich den Speicher für die eingelesene Zeichenkette lieder allokieren?

    Danke schonmals bis hierher und für folgende Antworten ^^°
     
  5. 26. November 2010
    AW: fork(), waitpid() und FileOperationen

    Du hast deine Programme sehr verschlechtert, wenn du einfach nur sizeof mit strlen ersetzt hättest wäre es besser als jetzt. Warum hast du den fgets anstatt scanf genommen? und dann auch noch so falsch...

    Wenn du dir was gutes tun willst lies sizeof, strlen, fgets, scanf hier nach: Galileo Computing :: C von A bis Z
     
  6. 29. November 2010
    AW: fork(), waitpid() und FileOperationen

    Nun ja,...
    das oben geschrieben Programm enthält alle Hinweise, Versuche und Misserfolge die ich tätigte um den genannten Fehler zu beseitigen.

    scanf() flog bei der Überwarbeitung raus da es nur bis zum leerzeichen einliest, was nicht gewollt ist.

    Ich weiß ich muss das nochmal überarbeiten, zumal viele exits fehlen et cetera

    Ich hab inzwischen auch überlegt ganz von fgets und scanf abzugehen und Zeichenweise einzulesen und zu schreiben bis zum EOF per Kommandozeile.

    Ebenso das einlesen/ausgeben des files.

    Vielleicht ist das ein besserer Ansatz.

    Allerdings bin ich nicht umsonst erst im Anfangsstadium des Programmierens ;-)

    Ob dus glaubst oder nicht, das Buch hab ich vor mir.

    Wenn du dort ins Kapitel open / write / read gehst, wirst du sehen das der Autor zB auch das sizeof verwendet, das ich zu Anfang verwendete.
    (kann es also sein, das es im Buch falsch genutzt wird?! )



    lg also erstmal.
    Ich denk mal ich werds heute nochmals überarbeiten.
     
  7. Video Script

    Videos zum Themenbereich

    * gefundene Videos auf YouTube, anhand der Überschrift.