进程间的管道通信

实验二

题目

JKQPFP.png
请编程建立 3 个并发协作进程或线程,它们分别完成 f(x,y)、f(x)、f(y)

解题思路

一个父进程创建两个子进程,父进程先获取用户输入的x,y的值,然后通过管道传给两个子进程,这两个子进程分别执行X的计算和Y的计算,然后将计算结果写回到自己的管道中,再由父进程读取子进程的管道,将数据读到父进程的管道中,从而得到最后的结果。

主要函数
1.fork函数

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;

2.pipe我们用中文叫做管道

函数原型 int pipe(int fd[2])
函数传入值 fd[2]:管道的两个文件描述符,之后就是可以直接操作者两个文件描述符
返回值 成功 0 失败 -1
fd一端只能用于读,由描述字fd[0]表示,称其为管道读端;另 一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。

3.read函数

ssize_t read(int fd, void * buf, size_t count);
函数说明:read()会把参数fd 所指的文件传送count 个字节到buf 指针所指的内存中. 若参数count 为0, 则read()不会有作用并返回0. 返回值为实际读取到的字节数, 如果返回0, 表示已到达文件尾或是无可读取的数据,此外文件读写位置会随读取到的字节移动

4.write函数

ssize_twrite(int handle, void *buf, int nbyte);
handle 是文件描述符;
buf是指定的缓冲区,即指针,指向一段内存单元;
nbyte是要写入文件指定的字节数;返回值:写入文档的字节数(成功);-1(出错)
write函数把buf中nbyte写入文件描述符handle所指的文档,成功时返回写的字节数,错误时返回-1

代码
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<stdlib.h>
#include<stdio.h>
#define READ 0//对管道读写的描述
#define WRITE 1


//声明计算f(x)和f(y)的函数
int  calX(int x);
int calY(int y);

int main(){
    //记录两个子进程的进程号
    pid_t pid_x,pid_y;

    int pipex[2],pipey[2],pipex2[2],pipey2[2];

     //创建四个管道
    pipe(pipex);
    int result_y = pipe(pipey);
    pipe(pipex2);
    int result_y2 = pipe(pipey2);

    pid_x = fork();
    if(pid_x<0){
        printf("进程创建失败\n");
    }else if (pid_x==0)
    {
        //进入函数f(x)
        int x1,x2;
        printf("This is child x,id is%d\n",getpid());

        //把不用的管道端口关掉
        close(pipex[WRITE]);
        close(pipex2[READ]);
        //子程序等待父程序输入x
        read(pipex[READ],&x1,sizeof(int));//把管道中的sizeof个字节独到变量x1中

        //通过函数计算
        x2=calX(x1);
        //写入管道
        write(pipex2[WRITE],&x2,sizeof(int));
        //关闭管道
        close(pipex[READ]);
        close(pipex2[WRITE]);
        //返回
        exit(EXIT_SUCCESS);


    }else
    {
        pid_y = fork();
        if(result_y<0||result_y2<0){
            printf("创建管道失败");
        }
        if(pid_y==0){
            //处理函数f(y)
            int y1,y2;
            printf("This is child y,id is%d\n",getpid());

             //把不用的管道端口关掉
             close(pipey[WRITE]);
             close(pipey2[READ]);
            //子程序等待父程序输入y
              read(pipey[READ],&y1,sizeof(int));//把管道中的sizeof个字节独到变量y1中

                                 printf("y1=%d\n",y1);
                                 printf("y2=%d\n",y2);

            //通过函数计算
            y2=calY(y1);
            
            //写入管道
             write(pipey2[WRITE],&y2,sizeof(int));
             //关闭管道
             close(pipey[READ]);
             close(pipey2[WRITE]);
              //返回
             exit(EXIT_SUCCESS);
        }
        if(pid_y>0){
            //父进程
            int inx,iny,ansx,ansy,ans;

            //规范输出
            sleep(1);
            printf("This is parent,id is%d\n ",getpid());
            //用户输入xy
            printf("\nplease input x and y\n");
            scanf("%d %d",&inx,&iny);

            printf("iny=%d\n",iny);

            //关闭不用的管道
            close(pipex[READ]);
            close(pipex2[WRITE]);
            close(pipey[READ]);
            close(pipey2[WRITE]);

            write(pipex[WRITE],&inx,sizeof(int));
            write(pipey[WRITE],&iny,sizeof(int));

            read(pipex2[READ],&ansx,sizeof(int));
            read(pipey2[READ],&ansy,sizeof(int));

            ans = ansx+ansy;
            
            printf("f(x)=%d\n",ansx);
            printf("f(y)=%d\n",ansy);
            printf("f(x+y)=%d\n",ans);

        }

    }
    
    exit(EXIT_SUCCESS);
    
}

int calX(int x){
    if(x==1){
        return 1;
    }else
    {
        return calX(x-1)*x;
    }
    
}

int calY(int y){
    if(y==1||y==2){
        return 1;
    }else
    {
        return calY(y-1)+calY(y-2);
    }
    
}
运行结果

JMhrS1.png
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值