3

I have a homework for uni. My homework is to make project using fork and using the method of pipelining to passing data through child and father processess. Well we need to creat two pipes. 1st pipe send a txt file that you will write in there the result of "Ps -A" and 2nd pipe will return the pids and their priorities. The proffessor said we should use dynamic arrays and through a structure we should pass the array of pids and the array of ppids back to child.Child prints both arrays on screen. The problem i have is child fills the arrays all good here but when i send them to the father, father doesn't simply read the arrays from struct and doesn't print anything on screen :( can you help me with this?

    struct dyna {
        int *pids;
        int *ppids;
    };

    int main(int argc, char *argv[]){
        int child_id;
        int pipe_pc[2],pipe_cp[2];
        int result_pc,result_cp;
        int lines1,i;

        if (argc!=2)//elegxos gia to an ta arguments pou edwse o xristis einai arxeio1 arxeio2 {
            fprintf(stderr,"Lathos arithmos orismaton.To swsto einai %s filename.txtn",argv[0]);
            exit(1);
        } else {
            result_pc=pipe(pipe_pc);
            if (result_pc==-1) exit(-1);
            result_cp=pipe(pipe_cp);
            if (result_cp==-1) exit(-1);

            struct dyna dyn;    

            child_id=fork();
            if (child_id==-1) exit(-1);
            //child
            if (child_id==0){
                char child_read_msg[buff];

                close(pipe_pc[1]);
                memset(child_read_msg,0,buff);
                read(pipe_pc[0],child_read_msg, buff);

                printf("nchild process:child read from father: %sn",child_read_msg);

                char child_write_msg[buff]="lol",lines[buff]="lines.txt",* pch,**grammes;
                FILE *pFile1,*pFile2;
                long lSize1,lSize2;
                char *buffer1,*command,*buffer2;
                size_t file1str,file2str;

                command = (char*)malloc(strlen("wc -l >")+strlen(child_read_msg)+strlen(lines));
                sprintf(command,"ps -A> %s",child_read_msg);
                system(command);

                //vazoume ta periexomena tou processes.txt se enan buffer
                pFile1 = fopen ( child_read_msg, "rb" ); 
                fseek (pFile1, 0 , SEEK_END);
                lSize1 = ftell (pFile1);
                rewind (pFile1);
                buffer1 = (char*) malloc (sizeof(char)*lSize1);
                if (buffer1 == NULL) {fputs ("Memory error",stderr); }
                file1str = fread (buffer1,1,lSize1,pFile1);
                if (file1str != lSize1) {fputs ("Reading error",stderr); }
                fclose(pFile1);


                //vriskoume ton arithmon grammon tou arxeiou
                sprintf(command,"wc -l %s>%s",child_read_msg,lines);
                system(command);

                pFile2 = fopen ( lines, "rb" ); 
                fseek (pFile2, 0 , SEEK_END);
                lSize2 = ftell (pFile2);
                rewind (pFile2);

                buffer2 = (char*) malloc (sizeof(char)*lSize1);
                if (buffer2 == NULL) {fputs ("Memory error",stderr); }
                file2str = fread (buffer2,1,lSize2,pFile2);
                if (file2str != lSize2) {fputs ("Reading error",stderr); }
                fclose(pFile2);
                sscanf(buffer2,"%d",&lines1); //lines1= arithmos grammon tou processes.txt
                sprintf(command,"rm -r %s",lines);
                system(command);
                free(buffer2);

                i=0;
                dyn.pids=(int *)calloc(sizeof(int),lines1); //desmeuei mnimi dinamika gia ton proto pinaka tis struct pou periexei ta pid
                pch = strtok (buffer1,"n");
                while (pch != NULL){
                    sscanf(pch,"%d",&dyn.pids[i]);
                    pch = strtok (NULL, "n");
                    i++;
                }


                dyn.ppids=(int *)calloc(sizeof(int),lines1);
                for (i=1;i<lines1;i++) /*Gemizei ton pinaka kai vazei tis proteraiotites tis kathe diergasias */ {
                    dyn.ppids[i]=getpriority(PRIO_PROCESS,dyn.pids[i]);
                }

                //for (i=1;i<lines1;i++){
                //printf("%dn",dyn.ppids[i]); 
                //}

                close(pipe_cp[0]);
                write(pipe_cp[1], &dyn,sizeof(dyn));

            }
            //parent
            else {
                close(pipe_pc[0]);
                write(pipe_pc[1], argv[1],strlen(argv[1]));
                printf("nparent process: father wrote to child: %sn",argv[1]);

                wait(NULL);

                close(pipe_cp[1]);//kleinoume to write-end, o pateras mono diabazei apo to pipe_cp
                read(pipe_cp[0],&dyn,sizeof(dyn));//parent diabazei ayto poy exei grapsei to paidi
                //prints the array with the priorities of the processes
                for (i=1;i<lines1;i++){
                    printf("%dn",dyn.ppids[i]);
                }

            }
            return 0;
        }
    }
Eric des Courtis
  • 5,135
  • 6
  • 24
  • 37

2 Answers2

3

write(pipe_cp[1], &dyn,sizeof(dyn)) simply transmits the two pointers from your struct, not the actual data they refer to. The addresses that these pointers hold would be meaningless in the parent process because it has a separate address space. Dereferencing them there will cause undefined behaviour, most probably a segmentation fault.

If you want your code to work this way, you need to declare the members of the struct to be arrays of a fixed size, not pointers. By doing so the struct essentially becomes a container that holds the two arrays in itself.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • Well i made the arrays static... but still couldn't get anything on the parent after reading the struct from the pipe :( Seems strange but i will see it again what goes wrong :( – Xristos Dimopoulos Apr 14 '11 at 14:18
1

There is a nice library for serializing C structures and arrays called tpl. I have been using it for quite some time and I am quite satisfied with it.

You might want to take a look at it and see how they do it.

Examples from the website using files (not limited to files, should work on anything that can do message passing):

/* Storing ids and usernames */
#include <tpl.h>

int main(int argc, char *argv[]) {
    tpl_node *tn;
    int id=0;
    char *name, *names[] = { "joe", "bob", "cary" };

    tn = tpl_map("A(is)", &id, &name);

    for(name=names[0]; id < 3; name=names[++id]) {
        tpl_pack(tn,1);
    }

    tpl_dump(tn, TPL_FILE, "users.tpl");
    tpl_free(tn);
}

And the reverse:

/* Reloading ids and usernames */
#include <tpl.h>

int main(int argc, char *argv[]) {
    tpl_node *tn;
    int id;
    char *name;

    tn = tpl_map("A(is)", &id, &name);
    tpl_load(tn, TPL_FILE, "users.tpl");

    while ( tpl_unpack(tn,1) > 0 ) {
        printf("id %d, user %s\n", id, name);
        free(name);
    }
    tpl_free(tn);
}

Another alternative would be to encode and decode in ASN.1 instead of making your own encoding. Plus you might get browny points for following standards.

Eric des Courtis
  • 5,135
  • 6
  • 24
  • 37