当前位置:文档之家› 实验二,进程通信,管道共享内存

实验二,进程通信,管道共享内存

操作系统实验报告实验二:进程通信(一)——管道及共享内存一、实验目的•了解进程之中相互通信的方式•加深对管道通信的了解•了解共享内存通信的程序设计方法•了解和熟悉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<stdio.h>#include<sys/types.h>#include<unistd.h>#include<sys/wait.h>#include<string.h>#include<stdlib.h>int main(){int x,fd[2];char buf[30],s[30];pipe(fd);while((x=fork())==-1);if(x==0){close(fd[0]);printf("Child Process!\n");strcpy(buf,"This is an example\n");write(fd[1],buf,30);exit(0);}else{close(fd[1]);printf("Parent Process!\n");read(fd[0],s,30);printf("%s\n",s);}}②截图:③结果和分析:创建一个管道,调用fork()函数产生两个进程,我的系统优先先执行父进程,比较疑惑,既然这样,管道中并没有数据是如何得出最后结果的,后来百度了一下解释说是因为管道本身是一种同步机制,并且printf执行的时间要比其他程序时间长得多,才会这样。

然后执行子程序,将数据写入管道,然后父程序打印出来2. 任务1(2)①代码:#include<stdio.h>#include<sys/types.h>#include<unistd.h>#include<sys/wait.h>#include<string.h>#include<stdlib.h>void fanzhuan(char *s){char *p=s+strlen(s)-1;char temp;while(s<p){temp=*p;*p--=*s;*s++=temp;}}int main(){int i,x,fd[2];char buf[20],s[20],m[20];strcpy(buf,"This is an example\n");pipe(fd);write(fd[1],buf,20);while((x=fork())==-1);if(x==0){printf("Child Process!\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("Parent Process!\n");read(fd[0],m,20);printf("%s\n",m);}}②截图:3. 任务2(1)①代码:#include<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>#include<stdio.h>#include<stdlib.h>int main(){key_t key=105;int shmid_1,shmid_2;if((shmid_1=shmget(key,1000,0644|IPC_CREAT))==-1){ perror("shmget shmid_1");exit(1);}printf("First shared memory identifier is %d\n",shmid_1);if((shmid_2=shmget(IPC_PRIVATE,20,0644))==-1){ perror("shmget shmid_2");exit(2);}printf("Second shared memory identifier is %d\n",shmid_2);exit(0);}②截图:③结果和分析:两次运行结束后,第二个共享标识符不一样,然后在每一次的ipcs 查看共享存储区的时候,最后一行也是不一样的。

原因是分配了两次,然后第一次有key值,第二次是没有的。

4. 任务2(2)①代码:程序1:#include<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>#define SHMKEY 105#define K 1024int shmid;int main(){int i,*pint;char *addr;extern void* shmat();extern cleanup();for(i=0;i<20;i++)signal(i,cleanup);shmid=shmget(SHMKEY,16*K,0777|IPC_CREAT);addr=shmat(shmid,0,0);printf("addr 0x%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<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>#define SHMKEY 105#define K 1024int shmid;int main(){int i,*pint;char *addr;extern void *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<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>#include<stdlib.h>#include<unistd.h>#include<sys/wait.h>#include<string.h>#include<stdio.h>int main(){key_t key=105;int shmid,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(),生成一个子程序,先让挂接到共享区,并且获得首地址,然后修改大写字母变成小写字母,然后脱离,最后再次调用父程序,获得首地址,然后输出共享区的内容。

相关主题