山大操作系统实验2

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

操作系统实验报告

——线程和进/线程管道通信实验

张咪软件四班一、实验要求

设有二元函数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) 。

二、实验目的

通过 Linux 系统中线程和管道通信机制的实验,加深对于线程控制和管道通信概念的理解,观察和体验并发进/线程间的通信和协作的效果 ,练习利用无名管道进行进/线程间通信的编程和调试技术。

三、实验环境

实验环境均为Linux操作系统,开发工具为gcc和g++。

四、实验思路

要实现三个函数,要创建三个进程,两个子进程和一个父进程。一个子进程实现f(x),另一个实现f(y)。因为f(x,y)=f(x)+f(y),所以在父进程和子进程间建立通信,子进程将当前值传给父进程,父进程进行计算。而且由于父进程的f(x,y)中的x和f(x)中的x一一对应,所以这些进程应该同步的并发向前走,否则f(x,y)的值就是错的。

五、算法设计

1.创建进程,每个子进程的执行代码段实现对应函数功能。

2.建立父进程和子进程间的通信。由于管道的读写默认的通信方式为同步读写方式,即如果管道读端无数据则读命令阻塞直到数据到达,反之如果管道写端有数据则写命令阻塞直到数据被读走。所以同步并发的问题可以通过管道实现。建立两个管道,pipe1和pipe2,f(x)通过pipe1向父进程写入f(x)的值。同理f(y)通过pipe2向父进程写入f(y)的值。父进程根据这两个值实现函数f(x,y)功能。

六、实验过程:

新建一个文件夹,在该文件夹中建立以下名为ppipe.c的C语言程序。

编写代码,保存。

输入gcc ppipe.c命令, 生成默认的可执行文件a.out。

执行a.out:。

执行并调试ppipe程序。

七、调试及实验结果

第一次编译时有很多拼写错误,错把perror打成prerror,不确定do{}while()语句的后面需不需要加分号,还漏掉了大括号,太粗心。

一开始错把pipe[0]和pipe[1]理解为管道1和管道2,后来经过仔细阅读实验指导,知道pipe[0]和pipe[1]指的是管道两端。

pipe系统调用的语法为: #include int pipe(int pipe_id[2]); pipe建立一个无名管道,pipe_id[0]中和pipe_id[1]将放入管道两端的描述符如果pipe执行成功返回0。. 出错返回-1.

八、源代码

#include

#include

#include

int main(int argc,char *argv[]){

int pid1,pid2;//两个子进程的进程号

int pipe1[2];//两个无名管道标号

int pipe2[2];

int x=1,y=1;

//如果创建管道失败,程序执行失败,退出

if(pipe(pipe1)<0){

perror("pipe1 创建不成功");

exit(EXIT_FAILURE);

}

if(pipe(pipe2)<0){

perror("pipe2 创建不成功");

exit(EXIT_FAILURE);

}

//创建子进程1

pid1=fork();

if(pid1<0){//如果子进程1创建失败,程序执行失败,退出

perror("process1 创建不成功");

exit(EXIT_FAILURE);

}

else if(pid1==0){//子进程1创建成功

//要在管道1 的1端进行写操作

//将管道1的0端和管道2关闭

close(pipe1[0]);

close(pipe2[0]);

close(pipe2[1]);

int fx=1;//fx的初始值

do{

if(x==1)fx=1;

else fx=fx*x;//f(x)函数

printf("child %d f(x):f(%d)=%d\n",getpid(),x++,fx);

write(pipe1[1],&fx,sizeof(int));//将fx的值取出写入管道1的1端}while(x<=9);//一直计算到x=9

close(pipe1[1]);

exit(EXIT_SUCCESS);//退出子进程1

}

else{//父进程

pid2=fork();//创建子进程2

if(pid2<0){//如果子进程2创建失败,退出

perror("process2 not create");

exit(EXIT_FAILURE);

}

if(pid2==0){//成功创建子进程2

//要在管道2 的1端进行写操作

//将管道1 和管道2 的0端关闭

close(pipe1[0]);

close(pipe1[1]);

close(pipe2[0]);

int fy=1,fy1=1,fy2=1;//初始值

do{

if(y==1||y==2)fy=1;

else{

fy1=fy2;

fy2=fy;

fy=fy1+fy2;

}//f(y)函数

printf("child %d f(y):f(%d)=%d\n",getpid(),y++,fy);

write(pipe2[1],&fy,sizeof(int));//将fy的值取出放入管道2的1端}while(y<=9);//一直计算到y=9

close(pipe2[1]);

exit(EXIT_SUCCESS);//退出子进程2

}

else{//父进程

//父进程要完成对管道1的0端和管道2的0端的读操作

//关闭管道1和管道2的1端

close(pipe1[1]);

close(pipe2[1]);

int m=1,n=1;

do{

read(pipe1[0],&x,sizeof(int));

read(pipe2[0],&y,sizeof(int));

printf("parent %d f(x,y):f(%d,%d)=%d\n",getpid(),m++,n++,x+y);

}while(m<=9&&n<=9);//一直计算到x=9,y=9

close(pipe1[0]);

close(pipe2[0]);

}

return EXIT_SUCCESS;//执行成功退出

}

}

相关文档
最新文档