实验二进程通信管道共享内存.docx
《实验二进程通信管道共享内存.docx》由会员分享,可在线阅读,更多相关《实验二进程通信管道共享内存.docx(12页珍藏版)》请在冰豆网上搜索。
实验二进程通信管道共享内存
操作系统实验报告
实验二:
进程通信
(一)——管道及共享内存
一、实验目的
∙了解进程之中相互通信的方式
∙加深对管道通信的了解
∙了解共享内存通信的程序设计方法
∙了解和熟悉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
(1)
①代码:
#include
#include
#include
#include
#include
#include
intmain()
{
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);
}
}
②截图:
③结果和分析:
创建一个管道,调用fork()函数产生两个进程,我的系统优先先执行父进程,比较疑惑,既然这样,管道中并没有数据是如何得出最后结果的,后来XX了一下解释说是因为管道本身是一种同步机制,并且printf执行的时间要比其他程序时间长得多,才会这样。
然后执行子程序,将数据写入管道,然后父程序打印出来
2.任务1
(2)
①代码:
#include
#include
#include
#include
#include
#include
voidfanzhuan(char*s){
char*p=s+strlen(s)-1;
chartemp;
while(s
temp=*p;
*p--=*s;
*s++=temp;
}
}
intmain()
{
inti,x,fd[2];
charbuf[20],s[20],m[20];
strcpy(buf,"Thisisanexample\n");
pipe(fd);
write(fd[1],buf,20);
while((x=fork())==-1);
if(x==0){
printf("ChildProcess!
\n");
read(fd[0],s,20);
//printf("%s\n",s);
fanzhuan(s);
write(fd[1],s,20);
exit(0);
}
else{
wait(NULL);
close(fd[1]);
printf("ParentProcess!
\n");
read(fd[0],m,20);
printf("%s\n",m);
}
}
②截图:
3.任务2
(1)
①代码:
#include
#include
#include
#include
#include
intmain(){
key_tkey=105;
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查看共享存储区的时候,最后一行也是不一样的。
原因是分配了两次,然后第一次有key值,第二次是没有的。
4.任务2
(2)
①代码:
程序1:
#include
#include
#include
#include
#include
#include
#include
#defineSHMKEY105
#defineK1024
intshmid;
intmain(){
inti,*pint;
char*addr;
externvoid*shmat();
externcleanup();
for(i=0;i<20;i++)
signal(i,cleanup);
shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT);
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(0);
}
程序2:
#include
#include
#include
#include
#include
#include
#include
#defineSHMKEY105
#defineK1024
intshmid;
intmain(){
inti,*pint;
char*addr;
externvoid*shmat();
shmid=shmget(SHMKEY,8*K,0777);
addr=shmat(shmid,0,0);
pint=(int*)addr;
for(i=0;i<256;i++)
printf("%d\n",*pint++);
}
②截图:
③结果和分析:
程序
(1)后台运行的时候,先创建一个共享内存段,然后挂接,得到共享区的地址,并且输出这个地址,然后pint的首地址就是共享区首地址,向共享区里面输入1,2,3,4,5.。
。
155。
程序
(2)执行的时候首先先挂接到这个共享区,然后向从首地址开始遍历,输出其中的内容
5.任务2(3)
①代码:
#include
#include
#include
#include
#include
#include
#include
#include
intmain(){
key_tkey=105;
intshmid,p1,i;
char*addr,*pint,temp;
shmid=shmget(key,30,0644|IPC_CREAT);
addr=shmat(shmid,0,0);
for(i=0;i<5;i++){
*addr='A'+i;
addr++;
}
while((p1=fork())==-1);
if(p1==0){
shmid=shmget(105,30,0644);
printf("success\n");
addr=shmat(shmid,0,0);
for(i=0;i<5;i++){
temp=*addr;
*addr=temp+32;
addr++;
}
addr=shmat(shmid,0,0);
printf("%s\n",addr);
shmdt(addr);
}
else{
sleep(5);
addr=shmat(shmid,0,0);
printf("%s\n",addr);
}
//printf("%s\n",addr);
shmctl(shmid,IPC_RMID,0);
exit(0);
}
②截图:
③结果和分析:
首先显示创建一个要求的共享区,然后挂接上去,得到共享区首地址,向共享区中输入一串大写字符串,然后调用fork(),生成一个子程序,先让挂接到共享区,并且获得首地址,然后修改大写字母变成小写字母,然后脱离,最后再次调用父程序,获得首地址,然后输出共享区的内容。
四、心得体会
在本次试验中,认识到了管道和共享内存的概念,这两种都是进程之中相互通信的非常高效的方式,管道一般多用于父进程和子进程之中,是一种同步机制。
共享内存用到的时候先要分配,然后获得地址,最后还需要释放。
需要注意的是,在修改共享内存中的值的时候,首先需要定位到共享内存的首地址,不然很容易会出错,其他程序用到共享内存的时候,首先也是需要先挂接到那边。