实验三进程通信一管道及共享内存.docx

上传人:b****4 文档编号:3590011 上传时间:2022-11-24 格式:DOCX 页数:13 大小:266.49KB
下载 相关 举报
实验三进程通信一管道及共享内存.docx_第1页
第1页 / 共13页
实验三进程通信一管道及共享内存.docx_第2页
第2页 / 共13页
实验三进程通信一管道及共享内存.docx_第3页
第3页 / 共13页
实验三进程通信一管道及共享内存.docx_第4页
第4页 / 共13页
实验三进程通信一管道及共享内存.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

实验三进程通信一管道及共享内存.docx

《实验三进程通信一管道及共享内存.docx》由会员分享,可在线阅读,更多相关《实验三进程通信一管道及共享内存.docx(13页珍藏版)》请在冰豆网上搜索。

实验三进程通信一管道及共享内存.docx

实验三进程通信一管道及共享内存

操作系统实验报告

实验三、进程通信

(一)

——管道及共享存

一、实验目的

1)加深对管道通信的了解

2)掌握利用管道进行通信的程序设计

3)了解共享存通信的程序设计方法

4)了解和熟悉Linux支持的共享存储区机制

二、实验容

任务一、

(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析。

(2)编写程序:

父进程利用管道将一字符串交给子进程处理。

子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。

任务二、

(1)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享存的情况,对两次的结果进行比较,并分析原因。

最后用ipcrm命令删除自己建立的共享存储区。

(有关ipcs和ipcrm介绍见后面一页)

(2)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。

运行结束后可以用ctrl+c结束程序1的运行。

(3)编写程序:

使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。

要求在父进程中生成一个30字节长的私有共享存段。

接下来,设置一个指向共享存段的字符指针,将一串大写字母写入到该指针指向的存贮区。

调用fork()生成子进程,让子进程显示共享存段中的容。

接着,将大写字母改成小写,子进程修改共享存中的容。

之后,子进程将脱接共享存段并退出。

父进程在睡眠5秒后,在此显示共享存段中的容(此时已经是小写字母)。

三、代码及运行结果分析

(1)阅读以上父子进程利用管道进行通信的例子(例1),写出程序的运行结果并分析

实验代码:

#include

main()

{intx,fd[2];

charbuf[30],s[30];

pipe(fd);

while((x=fork())==-1);

if(x==0)

{

close(fd[0]);

printf("ChildProcess!

\n");

strcpy(buf,"Thisisanexample\n");

write(fd[1],buf,30);

exit(0);

}

else{

close(fd[1]);

printf("ParentProcess!

\n");

read(fd[0],s,30);

printf("%s\n",s);

}

}

运行结果:

分析:

调用pipe(fd);创建一个管道后,接着调用fork()函数产生两个进程,首先开始执行子进程,关闭管道出口,通过管道入口向管道中写入容。

执行if语句后,进入else语句块开始父进程,管道入口关闭,通过管道出口端从管道中读取之前写入容,最后输出出来

(2)编写程序:

父进程利用管道将一字符串交给子进程处理。

子进程读字符串,将里面的字符反向后再交给父进程,父进程最后读取并打印反向的字符串。

实验代码:

#include

main()

{intx,count,left,right,temp,fd[2],fe[2];

charc,buf[30],s[30];

pipe(fd);

pipe(fe);

printf("pleaseinputalineofchar");

scanf("%s",buf);

while((x=fork())==-1);

if(x==0)

{

close(fd[0]);

close(fe[1]);

printf("ChildProcess!

\n");

write(fd[1],buf,30);

read(fe[0],buf,30);

printf("%s\n",buf);

exit(0);

}

else{

close(fd[1]);

close(fe[0]);

count=0;

do

{read(fd[0],&c,1);

s[count++]=c;

}while(c!

='\0');

printf("ParentProcess!

\n");

printf("%s\n",s);

count-=2;

for(left=0,right=count;left<=count/2;left++,right--){

temp=s[left];

s[left]=s[right];

s[right]=temp;

}

write(fe[1],s,30);

wait(0);

}

运行结果:

(3)阅读例2的程序,运行一次该程序,然后用ipcs命令查看系统中共享存储区的情况,再次执行该程序,再用ipcs命令查看系统中共享存的情况,对两次的结果进行比较,并分析原因。

最后用ipcrm命令删除自己建立的共享存储区。

(有关ipcs和ipcrm介绍见后面一页)

实验代码:

#include

#include

#include

main()

{

key_tkey=208;/*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/

intshmid_1,shmid_2;

if((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){

perror("shmgetshmid_1");exit

(1);

}

printf("Firstsharedmemoryidentifieris%d\n",shmid_1);

if((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){

perror("shmgetshmid_2");exit

(2);

}

printf("Secondsharedmemoryidentifieris%d\n",shmid_2);

exit(0);

}

运行结果:

Ipcs查看:

再次运行:

再次用ipcs查看:

Ipcrm删除

分析:

成功,返回共享存段的标识符,核中用于唯一的标识一个对象。

对存在于核存贮空间中的每个共享存段,核均为其维护着一个数据结构shmid_ds。

失败,返回-1,设置errno。

①第一个参数key(键值)用来创建IPC标识符,shmget()返回的标识符与key值一一对应,不同的key值返回不同的标识符。

②第二个参数size,决定了共享存段的大小(若访问已存在的存段,该参数可设为0)。

有最大字节数的限制

③第三个参数shmflag,用于设置访问权限及标识创建条件。

对两次的结果进行比较:

两次运行结束后的第二个共享标识符是不一样的。

在用ipcs查看时,共享存段中的关键字,共享存标识符,访问权限,字节等都是不一样的。

(4)每个同学登陆两个窗口,先在一个窗口中运行例3程序1(或者只登陆一个窗口,先在该窗口中以后台方式运行程序1),然后在另一个窗口中运行例3程序2,观察程序的运行结果并分析。

运行结束后可以用ctrl+c结束程序1的运行。

实验代码:

#include

#include

#include

#defineSHMKEY208/*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/

#defineK1024

intshmid;

main()

{

inti,*pint;

char*addr;

externchar*shmat();

externcleanup();

for(i=0;i<20;i++)signal(i,cleanup);

shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT);/*建立16K共享区SHMKEY*/

addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址*/

printf("addr0x%x\n",addr);

pint=(int*)addr;

for(i=0;i<256;i++)*pint++=i;

pause();/*等待接收进程读*/

}

cleanup()

{

shmctl(shmid,IPC_RMID,0);

exit();

}

运行结果:

分析:

首先系统通过调用shmctl对shmid指向的存段进行删除操作,接着系统调用shmget创建一个16*1024字节的共享存段,成功返回共享存段的标识符给shmid,系统再次调用shmat连接存段,返回该共享存段连接到调用进程地址空间上的地址addr。

实验代码:

#include

#include

#include

#defineSHMKEY208/*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/

#defineK1024

intshmid;

main()

{

inti,*pint;

char*addr;

externchar*shmat();

shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id*/

addr=shmat(shmid,0,0);/*连接共享区*/

pint=(int*)addr;

for(i=0;i<256;i++)

printf("%d\n",*pint++);/*打印共享区中的容*/

}

运行结果:

分析:

例3_1程序后台运行时,该程序开始执行,系统调用shmget创建一个8*1024字节的共享存段,再通过调用shmat挂接存段,由系统选择挂接地址,最终输出转换后的挂接地址。

需要指出的是,共享存储区机制只为通信进程提供了访问共享存储区的操作条件,而对通信的同步控制则要依靠信号量机制等才能完成。

(5)编写程序:

使用系统调用shmget(),shmat(),shmdt(),shmctl(),编制程序。

要求在父进程中生成一个30字节长的私有共享存段。

接下来,设置一个指向共享存段的字符指针,将一串大写字母写入到该指针指向的存贮区。

调用fork()生成子进程,让子进程显示共享存段中的容。

接着,将大写字母改成小写,子进程修改共享存中的容。

之后,子进程将脱接共享存段并退出。

父进程在睡眠5秒后,在此显示共享存段中的容(此时已经是小写字母)。

实验代码:

#include

#include

#include

#defineSHMKEY208/*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/

#defineK1024

intshmid;

main()

{

inti;

char*pint;

char*addr;

externchar*shmat();

externcleanup();

for(i=0;i<20;i++)signal(i,cleanup);

shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT);/*建立16K共享区SHMKEY*/

addr=shmat(shmid,0,0);/*挂接,并得到共享区首地址*/

printf("addr0x%x\n",addr);

pint=(char*)addr;

for(i='a';i<='e';i++)*pint++=i;

pause();/*等待接收进程读*/

}

cleanup()

{

shmctl(shmid,IPC_RMID,0);

exit();

}

#include

#include

#include

#defineSHMKEY208/*在实际实验过程中,为了避免每个同学建立的共享存储区关键字一样而相互干扰,关键字请用学号末3位*/

#defineK1024

intshmid;

main()

{

inti;

char*pint;

char*addr;

externchar*shmat();

shmid=shmget(SHMKEY,8*K,0777);/*取共享区SHMKEY的id*/

addr=shmat(shmid,0,0);/*连接共享区*/

pint=(char*)addr;

for(i=0;i<5;i++)

printf("%c\n",-32+*pint++);/*打印共享区中的容*/

}

结果无确运行

四、实验心得

通过本次实验了解了管道进程间通信形式,,管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;单独构成一种独立的文件系统:

管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统。

数据的读出和写入:

一个进程向管道中写的容被管道另一端的进程读出。

基本达到了本次实验的要求。

另外,对于共享存也有一定的了解,学会通过创建多个管道实现父子进程间的通信,对于共享存通信的工作机制也有了一定的了解,总之,本次实验自己收获了很多。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1