一、实验名称:实验五进程间通信(中)
二、实验日期:2014/3/27
三、实验目的:
1. 通过实验理解消息缓冲通信
2. 通过实验理解共享内存通信
3. 了解消息缓冲通信与内存共享通信之间的差异
四、实验的步骤和方法:
第五次小课进程间通信(中)
第一部分本周大课内容回顾
l Linux的IPC机制
Linux的IPC的含义是?IPC对象有哪几种?
1. IPC—Inter ProcessCommunication,进程间通信。
2. Linux的IPC机制包含如下IPC对象:消息队列、共享内存、信号量集(未讲)
3. IPC对象
Ø 每个IPC对象拥有唯一的IPC标识(ipc_ids和ipc_id)
Ø 每个IPC对象都有一个公共的ipc_perm结构,其中拥有一个唯一的key
Ø 理解IPC标识符与key的差异
Ø 理解ipc_perm结构中mode的定义
Ø ipc_perm在Linux中为kern_ipc_perm结构
消息队列是临界资源吗?对同一个消息队列进行访问的多个发送和接收进程存在何种制约关系?
消息队列通信的缺点是?
由shmget获得的共享内存区域是属于何种类型?(选项有物理内存页面 or磁盘文件)
共享内存通信相对消息队列通信的优点是?仍存在的问题?
l Linux消息缓冲通信
1.创建或获取消息队列标识:
int msgget(key_t key,int msgflag)
2.发送消息到指定队列:
int msgsnd(int msgid,struct msgbuf* msgp,intsize,int flag)
3.从指定队列中接收消息:
Int msgrcv(int msgid,struct msgbuf* msgp,int size,int type, int flag)
Type=0接收队列的第一个消息;>0接收类型type的第一个消息;<0接收小于或等于| type |的最低类型的第一个消息。
4.消息队列状态查询、修改或撤销队列:
int msgctl(int msgid, int cmd, struct msgid_ds*buf)
l Linux共享内存通信
shmget(key,size,flag):创建或获取共享内存id
shmat(int shmid,char *shmaddr,int msgflg,ulong*raddr)
shmat(int shmid,int *shmaddr,int msgflg,ulong*raddr):附接到共享内存
shmdt(viraddr):切断与共享内存的连接
shmctl(int shmid,int cmd,struct shmid_ds *buf):共享内存的状态查询、修改或撤销
第二部分进程间通信实验
1. 消息缓冲通信
2. 共享内存通信
进程间通信实验(1)
l 消息缓冲通信实验
利用消息缓冲通信方式,实现消息的发送与接收。
1. 发送进程sndfile.c将要发送的消息从键盘输入,每输入一行就作为一条消息发送,用end作为结束消息
2. 接收进程rcvfile.c从消息队列逐个接收信息并显示,用 end作为结束消息
3. 设消息队列的key值为1234
目的:了解缓冲消息通信的编程实现
理解要点:
1. my_msg结构就是msgbuf结构,需自定义
2. msgget()、msgsnd()、msgrcv()函数的使用
3. 采用各种方式或顺序运行此二进程,观察结果
解题思路:
2个程序:Sndfile.c和Rcvfile.c
1. Sndfile.c
定义消息缓冲区数据结构(my_msg);
通过msgget()创建消息队列;
while(1){
提示用户输入消息内容;
标准输入stdin送buffer;
buffer中的内容复制到消息缓冲;
通过msgsnd()发送消息;
消息为”end”结束;
}
2. Rcvfile.c
定义消息缓冲区数据结构(my_msg);
通过msgget()获取消息队列;
while(1){
通过msgrcv()接收消息内容;
显示消息;
消息为”end”结束;
}
Rcvfile.c
#include
#include
#include
#include
#include
#include
#define MAXMSG 512
struct my_msg //定义消息缓冲区数据结构
{
long int my_msg_type;
int i;
char some_text[MAXMSG];
} msg;
main()
{
int msgid;
msg.my_msg_type = 3;
msgid = msgget(12, 0666|IPC_CREAT); //获取消息队列, key为1234
while(1)
{
msgrcv(msgid, &msg, BUFSIZ, msg.my_msg_type, 0); //接收消息
printf("You wrote: %s and i = %d\n", msg.some_text, msg.i); //显示
if(strncmp(msg.some_text,"end",3) == 0)//消息为end则结束
break;
}
msgctl(msgid, IPC_RMID, 0); //删除消息队列
exit(0);
}
Rcvfile.c
#include
#include
#include
#include
#include
#include
#define MAXMSG 512
struct my_msg //定义消息缓冲区数据结构
{
long int my_msg_type;
int i;
char some_text[MAXMSG];
} msg;
main()
{
int msgid;
msg.my_msg_type = 3;
msgid = msgget(12, 0666|IPC_CREAT); //获取消息队列, key为1234
while(1)
{
msgrcv(msgid, &msg, BUFSIZ, msg.my_msg_type, 0); //接收消息
printf("You wrote: %s and i = %d\n", msg.some_text, msg.i); //显示
if(strncmp(msg.some_text,"end",3) == 0)//消息为end则结束
break;
}
msgctl(msgid, IPC_RMID, 0); //删除消息队列
exit(0);
}
改造:
1. 尝试使用发送与接收中的key值不一样或者设为0,看看是怎样的结果。
进程间通信实验(2)
l 共享内存通信实验(sndshm.c和rcvshm.c)
利用共享内存的方式,实现前一实验的基本目标
目的:了解共享内存通信
理解要点:
shmget()、shmat()、shmdt()、shmctl()的使用
理解消息缓冲通信与共享内存通信之间的差异
解题思路:
2个程序:Sndshm.c和Rcvshm.c
Sndshm.c
通过shmget()创建共享内存;
通过shmat()附接到近处虚拟地址空间;
while(1){
提示用户输入消息内容;
标准输入stdin送buffer;
buffer中的内容追加到共享内存;
消息为”end”结束;
}
Sndshm.c
#include
#include
#include
#include
#include
#include
main()
{
int shmid;
char *viraddr;
char buffer[BUFSIZ];
shmid = shmget(1234, BUFSIZ, 0666|IPC_CREAT); //创建共享内存
viraddr = (char*)shmat(shmid, 0, 0); //附接到共享内存
while(1)
{
puts("Enter some text:"); //提示用户输入信息
fgets(buffer, BUFSIZ, stdin); //将标准输入送入到缓冲区中
strcat(viraddr, buffer);//采用追加方式写到共享内存
if(strncmp(buffer,"end",3) == 0)//当输入的字符串为end时,终止循环
break;
}
shmdt(viraddr); //切断与共享内存的链接
exit(0);
}
Rcvshm.c
通过shmget()创建共享内存;
通过shmat()附接到近处虚拟地址空间;
显示消息;
通过shmdt()断开附接;
通过shmctl()撤销共享内存;
Rcvshm.c
#include
#include
#include
#include
#include
#include
main()
{
int shmid;
char *viraddr;
shmid = shmget(1234, BUFSIZ, 0666|IPC_CREAT); //创建共享内存
viraddr = (char *)shmat(shmid, 0, 0); //附接到共享内存
printf("Your message is: %S", viraddr); //输出共享内存的内容
shmdt(viraddr); //切断与共享内存的链接
shmctl(shmid, IPC_RMID, 0); //释放共享内存
exit(0);
}