实验二、进程通信(一)——管道及共享内存

实验二、进程通信(一)——管道及共享内存

一、实验目的

熟悉并掌握管道机制,并实现进程间通信
熟悉并掌握共享内存机制,并实现进程间通信

二、实验内容

任务一、
(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秒后,在此显示共享内存段中的内容(此时已经是小写字母)。

三、代码及运行结果分析

#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.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 Progress!\n");
strcpy(buf,"This is an example\n");
write(fd[1],buf,30);
exit(0);
}
else{//父进程
close(fd[1]);
printf("Parent Progress!\n");
read(fd[0],s,30);
printf("%s\n",s);
}
}

在这里插入图片描述
程序调用pipe()创建一个管道,接着调用fork()产生父子两个进程,首先执行子进程,关闭管道出口,通过管道入口向管道中写入内容。接着在父进程中关闭管道入口,通过管道出口从管道中读取内容输出。但是我的系统先执行父进程,感觉不太对,百度后发现解释说是因为管道本身是一种同步机制,并且printf执行的时间要比其他程序时间长的多,才会这样。

#include<stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
        int x,count,left,right,temp,fd[2],fe[2];
        char c,buf[30],s[30];
        pipe(fd);
        pipe(fe);
        printf("please input a line of char:\n");
        scanf("%s",buf);
        while((x=fork())==-1);
        if(x==0){
                close(fd[0]);
                close(fe[1]);
                printf("Child Process!\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("Parent Process!\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);
        }
}

在这里插入图片描述
程序调用pipe()创建2个管道fd和fe,接着调用fork()产生父子两个进程,首先执行子进程,关闭fd管道出口,fe管道入口,通过fd管道入口向管道中写入内容,fe管道输出内容。接着在父进程中关闭fd管道入口,fe管道出口,通过fd管道出口从管道中一个一个读取内容输出,倒序存入fe管道中。

#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int main()
{
key_t key=153; 
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);
return 0;
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

成功返回共享内存段标识符。对存在于内核存储空间中的每个共享内存段,内核均有shmid_ds。失败,返回-1。
参数key用来创建IPC标识符。参数size决定内存段的大小.参数shmflag,用于设置访问权限及标识创建条件。 
对比:第二次的共享内存段中的关键字,共享内存标识符,访问权限,字节等都是不一样的。

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 153
#define K  1024
int shmid;
void cleanup()
{
        shmctl(shmid,IPC_RMID,0);
        exit(0);
}
int main (){
        int i,*pint;
        char *addr;
        //extern char * shmat();
        //extern cleanup();
        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 ("addr 0x%x\n",addr);
        pint=(int *)addr;
        for (i=0;i<256;i++) *pint++=i;
        pause();/*等待接收进程读 */
}

#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include<unistd.h>
#include<signal.h>
#define SHMKEY 153
#define K  1024
int shmid;
int main (){
int i,*pint;
char *addr;
extern char * 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++);/*打印共享区中的内容*/
}

在这里插入图片描述
在这里插入图片描述

首先系统调用shmctl对shmid指向内存段进行删除,接着系统调用shmget创建共享内存段,返回标识符给shmid,系统再次调用shmat连接内存段,返回地址addr。程序2-3-1运行时,程序2-3-2开始执行,系统调用shmget创建共享内存段,再通过调用shmat挂接内存段,最终输出转换后的前255。

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 153
#define K 1024
int shmid_1,shmid_2;
int main ()
{
        int x,y,i,*pint;
        char *addr_1,*addr_2;
        char words[26]={'A','B','C','D','E','F','G','H','I','J',
        'K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','X'};
        shmid_1=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
        addr_1=shmat(shmid_1,0,0);/*挂接,并得到共享区首地址*/
        pint=(int *)addr_1;
        printf ("addr_1 0x%x\n",addr_1);
        for (i=0;i<26;i++) {
                *pint=words[i];
                pint++;
        }
        while((x=fork())==-1);
        if(x==0){
                shmid_2=shmget(SHMKEY,30*K,0777|IPC_CREAT); /*建立16K共享区SHMKEY */
                addr_2=shmat(shmid_2,0,0);/*挂接,并得到共享区首地址*/
                pint=(int *)addr_2;
                for(i=0;i<26;i++){
                        printf("%c ",*pint);
                        *pint=*pint+32;
                        pint++;
                        if(i==25)printf("\n");
                }
                y=shmdt(addr_2);
                exit(0);
        }else{
                sleep(5);
                pint=(int *)addr_1;
                for(i=0;i<26;i++){
                        printf("%c ",*pint);
                        pint++;
                        if(i==25)printf("\n");
                }
        }
}

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值