计算机科学与技术学院实验报告
实验题目:线程和进/线程管道通信实验
学号:XXXXXXXXXXXXX
日期:2014.3.26
班级:计算机 XXXX 班
姓名: XXXXXX
实验目的:
通过 Linux 系统中线程和管道通信机制的实验,加深对于线程控制和管道
通信概念的理解,观察和体验并发进/线程间的通信和协作的效果 ,练习利用无
名管道进行进/线程间通信的编程和调试技术。
实验要求:
设有二元函数 f(x,y) = f(x) + f(y)
, (x >1)
其中: f(x) = f(x-1) * x
, (x=1)
f(x)=1
f(y) = f(y-1) + f(y-2) ,
f(y)=1 ,
(y> 2)
(y=1,2)
编程建立 3 个并发协作进程,它们分别完成 f(x,y)、f(x)、f(y)
硬件环境: hp 计算机
处理器:Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz 2.50GHz
安装内存:4.00GB(3.85GB 可用)
软件环境:ubuntu13.10
实验步骤:
1、在声明各个存储数据所需变量后,请用户输入测试数据
2、使用 pipe()系统调用建立两个无名管道。使用 pipe 与 0 进行大小比较
来判断是否创建成功,若建立不成功程序退出,执行终止
3、使用 fork()建立第一个子进程,若 pid<0,则建立不成功程序退出,执行
终止;
4、子进程一计算 fy,并且负责从管道 1 的 1 端写入 fx。
5、父进程开始执行,再使用 fork()建立第二个子进程,若 pid<0,则建立不
成功程序退出,执行终止;
6、子进程二计算 fy,并且负责从管道 2 的 1 端写入 fy。
7、子进程二执行结束,父进程开始执行。父进程从管道 1 的 0 端,管道 2 的
0 端分别读取 fx 和 fy。计算 fxy。关闭管道,执行结束。
实现方式:
参照示例实验,使用 C 语言实现。
体会:
因为 fx 和 fy 都要和 fxy 进行通信,而二者之间不需要通信,所以建立两和
管道即可。而且,该实验进行之后无需保存管道,所以建立无名管道即可。
一个进程通过管道的一端向管道里面写入内容,另一个进程可以从这个管
道的另一端读到上一个进程写入的内容。管道是单向的。
使用 C 语言写程序对我来说依然很难,我都是基于示例实验以及别人的实验
做出来的,虽然借鉴了一些示例代码,但是我认真做了,还是很有收获的,在课
堂上学习了进程间的通信后再进行实验,理解得更透彻了。
在写程序中还是有细节没有注意到,比如在声明变量时写的是 pid1 和 pid2,
但是在程序中却把第一个子进程用 pid 表示的。诸如此类的错误出现了好多,还
是要加强细致程度。
实验结果:
Please input x and y
23
14
child pid 4467 is running, now fx=862453760 (x=23)
child pid 4468 is running, now fy=377 (y=14)
parent pid 4466 is running, now fxy=862454137 (x=23,y=14)
分析:
用户输入测试数据(Please input x and y
)以后,程序先创建了两个管道用以 fx 和 fxy 之间通信,以及 fy 和 fxy 之间通
信。然后又创建了两个进程,用以分别从管道中读取 x 和 y,并且计算 fx 和 fy,
再将 fx 和 fy 写入管道。在子进程退出前会报告其进程号和当前的 fx 或 fy 的值
(child pid 4467 is running, now fx=862453760 (x=23)
;child pid 4468 is running, now fy=377 (y=14) )
。最后父进程执行,从管道中读取 fx 和 fy 的值,计算 fxy,然后报告其进程号
和 当 前 的 fxy 的 值 ( parent pid 4466 is running, now fxy=862454137
(x=23,y=14) )。至此,执行完成。
附录:实验程序
#include
#include
#include
int main(int argc, char *argv[])
{
int pid1,pid2;//进程号
int pipe1[2]; //存放第一个无名管道标号
int pipe2[2]; //存放第二个无名管道标号
int fx,fy,fxy;//存放计算结果
int x,y;
//接受用户输入 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((pid1=fork()) <0){
perror("process1 create failed");
exit(EXIT_FAILURE);
}
if(pid1 == 0){
//第一个子进程负责从管道 1 的 1 端写,所以关闭管道 1 的 0 端
close(pipe1[0]);
//计算 fx 并输出到管道
fx = Fx(x);
printf("child
running,
fx=%d
now
pid
%d
is
(x=%d)
\n",getpid(),fx,x);
write(pipe1[1],&fx,sizeof(int));
//读写完成后,关闭管道 1 的 1 端
close(pipe1[1]);
//子进程 1 执行结束
exit(EXIT_SUCCESS);
}
else{
//父进程开始执行
//再创建一个子进程,建立不成功程序退出,执行终止
if((pid2=fork()) <0){
perror("process2 create failed.");
exit(EXIT_FAILURE);
}else if (pid2 == 0){
//子进程 2 开始执行
//管道 2 的 1 端写,所以关闭管道 2 的 0 端
close(pipe2[0]);
fy = Fy(y);
printf("child
running,
pid
%d
is
now
fy=%d
(y=%d)
\n",getpid(),fy,y);
write(pipe2[1],&fy,sizeof(int));
close(pipe2[1]);
//子进程 2 执行结束
exit(EXIT_SUCCESS);
}
//转回到父进程
//父进程从管道 1 的 0 端,管道 2 的 0 端读
//所以先关闭管道 1 的 1 端和管道 2 的 1 端
close(pipe1[1]);
close(pipe2[1]);
read(pipe1[0],&fx,sizeof(int));
read(pipe2[0],&fy,sizeof(int));
fxy = Fxy(fx,fy);
printf("parent pid %d is running, now fxy=%d (x=%d,y=%d)
\n",getpid(),fxy,x,y);
close(pipe1[0]);
close(pipe2[0]);
}
//父进程执行结束
return EXIT_SUCCESS;
}
//函数 f(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;
}