山东大学2018级操作系统实验二

题目描述

设有二元函数 f(x,y) = f(x) + f(y),
其中,f(x)=f(x-1)*x (x>1), f(x)=1 (x=1)
f(y) = f(y-1) + f(y-2) (y> 2), f(y)=1 (y=1,2)
请编程建立 3个并发协作进程或线程,它们分别完成 f(x,y)、f(x)、f(y)。

实验思路

三个函数,对应创建三个进程:两个子进程f(x)和f(y),一个父进程f(x,y)。要实现父子进程间的通信,子进程将当前值传给父进程,父进程进行计算。这些进程应该同步并发向前走,否则父进程计算的值将会错误。由于管道默认是同步读写,即如果管道读端无数据则读命令阻塞直到数据到达,反之如果管道写端有数据则写命令阻塞直到数据被读走。所以同步并发的问题可以通过管道实现。建立4个管道,分别为pipe11[2],pipe12[2],pipe21[2],pipe22[2]。
f(x)的子进程通过pipe11[2],pipe12[2]与父进程通信,f(y)的子进程通过pipe21[2],pipe22[2]与父进程通信,父进程根据这两个值实现f(x,y)功能。

实验涉及的知识点

1、管道通信机制:
管道pipe 是进程间通信最基本的一种机制。在内存中建立的管道称为无名管道,在磁盘上建立的管道称为有名管道。无名管道随着进程的撤消而消失,有名管道则可以长久保存,shell 命令符| 建立的就是无名管道,而shell 命令mkfifo 建立的是有名管道。两个进程可以通过管道一个在管道一端向管道发送其输出,给另一进程可以在管道的另一端从管道得到其输入.管道以半双工方式工作,即它的数据流是单方向的.因此使用一个管道一般的规则是读管道数据的进程关闭管道写入端,而写管道进程关闭其读出端。管道既可以采用同步方式工作也可以采用异步方式工作。
pipe 系统调用的语法为:
#include <unistd.h>
int pipe(int pipe_id[2]);
pipe 建立一个无名管道,pipe_id[0]中和pipe_id[1]将放入管道两端的描述符如果pipe 执行成功返回0,出错返回-1.
管道读写的系统调用语法为:
#include <unistd.h>
ssize_t read(int pipe_id,const void *buf,size_t count);
ssize_t write(int pipe_id,const void *buf,size_t count);
read 和write 分别在管道的两端进行读和写。
pipe_id 是pipe 系统调用返回的管道描述符。
Buf是数据缓冲区首地址, count说明数据缓冲区以size_t 为单位的长度。
read 和write 的返回值为它们实际读写的数据单位。
注意管道的读写默认的通信方式为同步读写方式,即如果管道读端无数据则读者阻塞直到数据到达,反之如果管道写端有数据则写者阻塞直到数据被读走。

源代码

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#define READ 0
#define WRITE 1

int fx(int x);
int fy(int y);
int main()
{
    pid_t pid1, pid2; //child 1,2

    int pipe11[2], pipe12[2], pipe21[2], pipe22[2]; //4 pipes
    int x, y;                                       //input variable

    if (pipe(pipe11) < 0)
    {
        perror("pipe  create failed\n");
        exit(EXIT_FAILURE);
    }
    if (pipe(pipe12) < 0)
    {
        perror("pipe  create failed\n");
        exit(EXIT_FAILURE);
    }
    if (pipe(pipe21) < 0)
    {
        perror("pipe  create failed\n");
        exit(EXIT_FAILURE);
    }
    if (pipe(pipe22) < 0)
    {
        perror("pipe  create failed\n");
        exit(EXIT_FAILURE);
    }

    pid1 = fork();
    if (pid1 < 0)
    {
        fprintf(stderr, "child1 fork failed\n");
        exit(EXIT_FAILURE);
    }
    else if (pid1 == 0)
    {
        int x, ansX;
        //printf("This is child 1\n");

        close(pipe11[WRITE]);
        close(pipe12[READ]);
        //wait parent write to child1
        read(pipe11[READ], &x, sizeof(int));

        ansX = fx(x);
        //write to parent
        write(pipe12[WRITE], &ansX, sizeof(int));

        close(pipe11[READ]);
        close(pipe12[WRITE]);

        exit(EXIT_SUCCESS);
    }
    else
    {
        //printf("This is  parent to fork 2\n");
        pid2 = fork();
        if (pid2 < 0)
        {
            fprintf(stderr, "child2 fork failed\n");
            exit(EXIT_FAILURE);
        }
        else if (pid2 == 0)
        {
            int y, ansY;
            //printf("This is child 2\n");

            close(pipe21[WRITE]);
            close(pipe22[READ]);
            //wait parent write to child2
            read(pipe21[READ], &y, sizeof(int));

            ansY = fy(y);
            //write to parent
            write(pipe22[WRITE], &ansY, sizeof(int));

            close(pipe21[READ]);
            close(pipe22[WRITE]);

            exit(EXIT_SUCCESS);
        }
        else
        {
            int x, y, ansX, ansY, ans;
            //printf("This is  parent \n");

            //input
            //printf("x = \n");
            //  scanf("%d", &x);
            x = 3;
            //printf("y = \n");
            //   scanf("%d", &y);
            y = 4;

            close(pipe11[READ]);
            close(pipe12[WRITE]);
            close(pipe21[READ]);
            close(pipe22[WRITE]);

            //write to child1 x
            write(pipe11[WRITE], &x, sizeof(int));
            //write to child2 y
            write(pipe21[WRITE], &y, sizeof(int));

            //read answer X of  child1
            read(pipe12[READ], &ansX, sizeof(int));
            //read answerY  of  child2
            read(pipe22[READ], &ansY, sizeof(int));

            //calculate
            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 fx(int x)
{
    if (x <= 1)
    {
        return 1;
    }
    else
    {
        return fx(x - 1) * x;
    }
}
int fy(int y)
{
    if (y <= 2)
    {
        return 1;
    }
    else
    {
        return fy(y - 1) + fy(y - 2);
    }
}
  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值