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