Передача структуры с двумя динамическими массивами через трубу и вилку - PullRequest
3 голосов
/ 14 апреля 2011

У меня есть домашняя работа для универа. Моя домашняя работа состоит в том, чтобы сделать проект с использованием fork и с помощью метода конвейерной передачи для передачи данных через процессы потомков и отцов. Ну, нам нужно создать две трубы. 1-й канал отправляет txt-файл, в который вы напишете результат «Ps -A», а 2-й канал вернет pids и их приоритеты. Профессор сказал, что мы должны использовать динамические массивы, и через структуру мы должны передать массив pids и массив ppids обратно в child.Child выводит оба массива на экран. У меня проблема в том, что child заполняет массивы все хорошо, но когда я отправляю их отцу, папа не просто читает массивы из struct и ничего не печатает на экране :( Можете ли вы помочь мне с этим?

    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;
        }
    }

Ответы [ 2 ]

3 голосов
/ 14 апреля 2011

write(pipe_cp[1], &dyn,sizeof(dyn)) просто передает два указателя из вашей структуры, а не фактические данные, на которые они ссылаются. Адреса, которые содержат эти указатели, были бы бессмысленными в родительском процессе, потому что он имеет отдельное адресное пространство. Разыменование их там приведет к неопределенному поведению, скорее всего, к ошибке сегментации.

Если вы хотите, чтобы ваш код работал таким образом, вам нужно объявить члены структуры массивов фиксированного размера, а не указатели. Таким образом, структура по существу становится контейнером, который содержит два массива в себе.

1 голос
/ 29 июня 2012

Есть хорошая библиотека для сериализации структур и массивов C, которая называется tpl .Я использую его в течение достаточно долгого времени, и я вполне доволен им.

Возможно, вы захотите взглянуть на него и посмотреть, как они это делают.

Примеры с сайта, использующегофайлы (не ограниченные файлами, должны работать на всем, что может передавать сообщения):

/* 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);
}

И наоборот:

/* 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);
}

Другой альтернативой будет кодирование и декодирование в ASN.1 вместо создания собственной кодировки.Кроме того, вы можете получить очки за соблюдение стандартов.

...