山东大学2023操作系统实验2
目录
(1)操作系统实验2内容:
(2)完成方式:
(3)使用函数和功能:
1.pipe函数与有关的功能
2.pipe的返回值
3.pipe的参数
4.使用事项:
(4)实现代码
(5)实现效果
(1)操作系统实验2内容:
创建三个并行的进程,分别完成计算F(x),F(y),F(x,y)三个函数的计算
(2)完成方式:
实验环境:ubuntn22.04 vscode2023
函数计算:其中两个一维函数可以使用递归计算(fy即为斐波那契数列的计算方式,这两个函数可以使用dp的方式完成优化,这里因为数据量较小不再实现) , 计算二维函数需要使用管道通信,将前两个进程的数据通过管道发送到另一个管道中,实现进程的通信.
并行进程:三个并行进程建立方式是,每次建立子进程后,判断当前的进程是否为父进程,如果当前为父进程,则可以再创建一个进程,这就是三个并行进程的创建方式.
其实这就是fork函数的本质:当某个进程根据fork函数创建子进程的时候,会给根据这个函数创建的两个进程分别配一个返回值,父进程得到的返回值是大于0的,而子进程得到的返回值是0.
一个fork函数只能针对两个进程赋值,但是一个进程(比如父进程)可以得到很多fork函数的返回值
(3)使用函数和功能:
1.pipe函数与有关的功能
int pipe(int port[2]);
在cpp中,使用这样的方式创建管道,管道也是一种资源,不应该独属于某个进程.
管道的特点就是只有管道为满的时候,才能读取.在管道为空的时候才能读入,不存在两个端口都开放的情况
在cpp中的体现为:只有用close关闭指定的端口,另一个端口才能正常工作:例如没有关闭管道输入端口,就从管道的输出端口读取数据,会发生阻塞
2.pipe的返回值
数值,当返回值为0的时候,代表这个管道成功创建
3.pipe的参数
是一个两个长度的整数数组,port[0]为管道的输出端口的表示(可以读出),port[1]为管道的输入端口的表示(可以写入)
当一个pipe创建成功的时候,端口的标识符会自动打入这个数组中
4.使用事项:
(1)读取时:要先关闭管道的写入端口,才能从输出端口进行读出
read函数的三个参数分别为:
close(port[1]);
read(port[0],数据,要传输的数据长度);
注意read的第二个函数要传入引用的形式
(2)输出时:大同小异
close(port[0]);
write(port[1],数据,要传输的数据长度);
(4)实现代码
#include <bits/stdc++.h>
using namespace std;
int fx(int x){
if(x==1) return 1;
else return fx(x-1)*x;
}
int fy(int y){
if(y==1||y==2) return 1;
else return fy(y-1)+fy(y-2);
}
int main(int args,char * arg[]){
// try to create a son_process
int Fx[2];
if(pipe(Fx)==0) cout<<"pipe Fy is created"<<endl;
int Fy[2];
if(pipe(Fy)==0) cout<<"pipe Fy is created"<<endl;
//create a process as my first son process
pid_t pid=fork();
if(pid==0){// Fx
close(Fx[0]);
int x; cout<<"please input a number as x"<<endl;
cin>>x;
x=fx(x);
write(Fx[1],&x,8); cout<<"F(x)="<<x<<endl;
}else if(pid>0){
pid_t pid1=fork(); //create a process as my second son process
if(pid1==0){//Fy
close(Fy[0]);
int y; cout<<"please input a number as y"<<endl;
cin>>y;
y=fy(y);
write(Fy[1],&y,8); cout<<"F(y)="<<y<<endl;
}else if(pid1>0){//Fxy
close(Fx[1]);
close(Fy[1]);
int x,y;
read(Fx[0],&x,8);
read(Fy[0],&y,8); cout<<"F(x,y)="<<x+y<<endl;
}
}
return 0;
}
(5)实现效果