通过管道和叉子传递具有 2 个动态数组的结构

发布于 2024-11-01 06:43:42 字数 4733 浏览 1 评论 0原文

我有一份大学作业。我的作业是使用fork制作项目,并使用管道的方法通过子进程和父进程传递数据。那么我们需要创建两个管道。第一个管道发送一个 txt 文件,您将在其中写入“Ps -A”的结果,第二个管道将返回 pid 及其优先级。教授说我们应该使用动态数组,并通过一个结构将 pid 数组和 ppid 数组传递回 child。Child 在屏幕上打印这两个数组。我遇到的问题是孩子在这里填充数组一切都很好,但是当我将它们发送给父亲时,父亲并不简单地从结构中读取数组,也不在屏幕上打印任何内容:(你能帮我解决这个问题吗?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

断爱 2024-11-08 06:43:42

write(pipe_cp[1], &dyn,sizeof(dyn)) 只是传输结构中的两个指针,而不是它们引用的实际数据。这些指针所保存的地址在父进程中毫无意义,因为它具有单独的地址空间。取消引用它们会导致未定义的行为,很可能是分段错误。

如果您希望代码以这种方式工作,则需要将结构体的成员声明为固定大小的数组,而不是指针。通过这样做,该结构本质上成为一个容器,其中包含两个数组。

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.

我做我的改变 2024-11-08 06:43:42

有一个不错的用于序列化 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 而不是制作您自己的编码。另外,您可能会因遵循标准而获得加分。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文