实验二
题目
(请编程建立 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);
}
}
运行结果