操作系统的第二个实验是关于进程和线程间的通信的。我们实验的例子就是用线程来通信,线程间通信很简单,他们共有一些相同的资源。而且大一的学习用java线程实现多对多聊天也是很简单的。而进程之间的通信就必须通过消息传递或者共享内存来实现。这个实验就是使用无名管道来实现进程间信息的传递的。
实验题目:
设有二元函数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(y)/f(x)
实验思路:利用无名管道通信,由于三个进程,先分别叫做fxy,fx,fy则fx要与fxy通信,使用一条管道,fy也要与fxy通信,使用另一条管道。除此之外无需其他通信。所以两条管道足够,在实验的时候周边很多同学第一反应都是三个管道,这实际上有点浪费了。
实验代码及说明:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char *argv[]) { int pid,pid2;//进程号 int pipe1[2]; //存放第一个无名管道标号 int pipe2[2]; //存放第二个无名管道标号 int fx,fy,fxy; int x,y; //接受用户输入 printf("Please input x and y\n"); scanf("%d %d",&x,&y); //使用 pipe()系统调用建立两个无名管道。建立不成功程序退出,执行终止 if(pipe(pipe1) < 0){ perror("pipe1 create failed"); exit(EXIT_FAILURE); } if(pipe(pipe2) < 0){ perror("pipe2 create failed"); exit(EXIT_FAILURE); } //使用 fork()建立第一个子进程,不成功退出 if((pid=fork()) <0){ perror("process1 create failed"); exit(EXIT_FAILURE); } else if(pid == 0){ //第一个子进程负责从管道1的1端写 close(pipe1[0]); //计算fx并输出到管道 fx = Fx(x); printf("child pid is %d fx=%d (x=%d) \n",getpid(),fx,x); write(pipe1[1],&fx,sizeof(int)); //读写完成后,关闭管道 close(pipe1[1]); //子进程执行结束 exit(EXIT_SUCCESS); }else{ //父进程 //再创建一个子进程 if((pid2=fork()) <0){ perror("process2 create failed."); exit(EXIT_FAILURE); }else if (pid2 == 0){ //管道2的1端写 close(pipe2[0]); fy = Fy(y); printf("child pid is %d fy=%d (y=%d) \n",getpid(),fy,y); write(pipe2[1],&fy,sizeof(int)); close(pipe2[1]); //退出该线程 exit(EXIT_SUCCESS); } //父进程负责从管道1的0端,管道2的0端读 close(pipe1[1]); close(pipe2[1]); read(pipe1[0],&fx,sizeof(int)); read(pipe2[0],&fy,sizeof(int)); fxy = fx + fy; printf("parent pid is %d fxy=%d (x=%d,y=%d) \n",getpid(),fxy,x,y); close(pipe1[0]); close(pipe2[0]); } //父进程执行结束 return EXIT_SUCCESS; } //函数(xy) int Fxy(const int fx,const int fy){ return fx+fy; } //函数f(y) int Fy(const int y){ return y==1||y==2 ? 1:(Fy(y-1)+Fy(y-2)); } //函数f(x) int Fx(const int x){ return x==1? 1:Fx(x-1)*x; }