C中的管道 - 在我的程序中读写

时间:2018-01-01 21:41:43

标签: c pipe

我希望我的程序能够显示如下结果:

child: 2 4 6 8 10  
parent: 3 6 9 12 15  
child 12 14 16 18 20  
parent 18 21 24 27 30  

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

main(int argc,char *argv[]){
int i=0,tube1[2],tube2[2],pid,tube3[2];
if(pipe(tube1)||pipe(tube2)==-1){
perror("pipe");
exit(0);
}
pid=fork();

while(i<100){

if(pid==0){
printf("fils ");

do{
i=i+2;
printf("%d ",i);
}while(i%5!=0);


write(tube1[1],&i,sizeof(int));

read(tube2[0],&i,sizeof(int));


}

else{



printf("pere ");
read(tube1[0],&i,sizeof(int));
do{

i=i+3;
printf("%d ",i);
}while(i%5!=0);


write(tube2[1],&i,sizeof(int));



}

printf("\n");








}
close(tube1[1]);
close(tube1[0]);
close(tube2[1]);
close(tube2[0]);
}

但我的课程有问题;我不明白为什么。

1 个答案:

答案 0 :(得分:2)

清理后,您的代码如下所示:

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

int main(void)
{
    int i = 0, tube1[2], tube2[2], pid;
    if (pipe(tube1) == -1 || pipe(tube2) == -1)
    {
        perror("pipe");
        exit(0);
    }
    pid = fork();

    while (i < 100)
    {
        if (pid == 0)
        {
            printf("fils ");
            do
            {
                i = i + 2;
                printf("%d ", i);
            } while (i % 5 != 0);
            putchar('\n');

            write(tube1[1], &i, sizeof(int));
            read(tube2[0], &i, sizeof(int));
        }
        else
        {
            printf("pere ");
            read(tube1[0], &i, sizeof(int));
            do
            {
                i = i + 3;
                printf("%d ", i);
            } while (i % 5 != 0);
            putchar('\n');

            write(tube2[1], &i, sizeof(int));
        }
    }
    close(tube1[1]);
    close(tube1[0]);
    close(tube2[1]);
    close(tube2[0]);
}

一个变化是进程在写入一系列数字后输出换行符,而不是等到读/写操作之后。

循环是复杂的,因为你有一个外部while (i < 100)循环,然后每个进程都有一个递增i的内部循环。然后,为了进一步复杂化,子进程将其当前值i发送给父进程,父进程在其循环中使用它,然后父进程将其自己的值i发送给子进程,孩子用i的新值恢复工作;冲洗并重复。输出是:

fils 2 4 6 8 10 
pere 13 16 19 22 25 
fils 27 29 31 33 35 
pere 38 41 44 47 50 
fils 52 54 56 58 60 
pere 63 66 69 72 75 
fils 77 79 81 83 85 
pere 88 91 94 97 100 

您可以看到孩子生成的值为10;那么父母将它从孩子那里得到的值加上3(因此是13)并迭代;然后它向孩子发送25,这增加2(因此27)并迭代;等等。

要获得您要搜索的结果,您需要从值中解耦同步中使用的值以控制循环。你也遇到了一个问题,因为孩子会尝试比父母跑更长的时间,但幸运的是,它会得到一个SIGPIPE信号,当它试图写入父母已关闭的管道时会死亡 - 或者说,如果它关闭了它没有使用的管道的末端。生成换行符后刷新标准输出也是一个好主意。这些变化导致:

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

int main(void)
{
    int i = 0, tube1[2], tube2[2], pid;
    if (pipe(tube1) == -1 || pipe(tube2) == -1)
    {
        perror("pipe");
        exit(1);
    }
    pid = fork();
    if (pid < 0)
    {
        perror("fork");
        exit(1);
    }
    if (pid == 0)
    {
        close(tube1[0]);
        close(tube2[1]);
    }
    else
    {
        close(tube1[1]);
        close(tube2[0]);
    }

    while (i < 100)
    {
        if (pid == 0)
        {
            printf("fils ");
            do
            {
                i = i + 2;
                printf("%d ", i);
            } while (i % 5 != 0);
            putchar('\n');
            fflush(stdout);

            int j = 0;
            write(tube1[1], &j, sizeof(int));
            read(tube2[0], &j, sizeof(int));
        }
        else
        {
            int j = 0;
            read(tube1[0], &j, sizeof(int));

            printf("pere ");
            do
            {
                i = i + 3;
                printf("%d ", i);
            } while (i % 5 != 0);
            putchar('\n');
            fflush(stdout);

            write(tube2[1], &j, sizeof(int));
        }
    }
    close(tube1[1]);
    close(tube1[0]);
    close(tube2[1]);
    close(tube2[0]);
}

其输出是:

fils 2 4 6 8 10 
pere 3 6 9 12 15 
fils 12 14 16 18 20 
pere 18 21 24 27 30 
fils 22 24 26 28 30 
pere 33 36 39 42 45 
fils 32 34 36 38 40 
pere 48 51 54 57 60 
fils 42 44 46 48 50 
pere 63 66 69 72 75 
fils 52 54 56 58 60 
pere 78 81 84 87 90 
fils 62 64 66 68 70 
pere 93 96 99 102 105 
fils 72 74 76 78 80 

请注意,子项未达到100,因为父项退出,并且父项超过100,因为检查发生在外部循环上,而不是内部循环。

我保留了你的循环组织,但是它是我自己的代码,它将有两个函数 - be_childish()be_parental() - 它们将在fork之后调用,并且每个函数都会运行它们自己的相关循环。管道将传递给功能部件,他们会更好地清理。请注意,程序结束时4个close()调用中的2个将失败,因为这些管道描述符先前已关闭。分开哪些是繁琐的;最好将代码拆分为函数。