Linux 内存共享与消息队列

共享内存
共享共存区域是被多个进程共享的一部分物理内存。如果多个进程都
把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信。共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。
共享内存实现分为两个步聚:
一、创建共享内存,使用shmget函数。
二、映射共享内存,将这段创建的共享内存映射到具体的进程空间去
,使用shmat函数。
系统调用:shmget()
原型:int shmget(key_t key,int size,int shmflg);
返回值:如果成功,返回共享内存段标识符。如果失败,则返回-1;
errno=EINVAL(无效的内存段大小)
      EEXIST(内存段已经存在,无法创建)
      EIDRM(内存段已经被删除)
      ENOENT(内存段不存在)
      EACCES(权限不够)
      ENOMEM(没有足够的内存来创建内存段)

系统调用:shmat();
原型:int shmat(int shmid,char *shmaddr, int shmflg);
返回值:如果成功,则返回共享内存段连接到进程中的地址。如果失
败,则返回-1;
errno=EINVAL(无效的IPC ID值或者无效的地址)
      ENOMEM(没有足够的内存)
      EACCES(存取权限不够)
当一个进程不在需要共享的内存段时,它将会把内存段从其地址空间
中脱离。
系统调用:shmdt();
调用原型:int shmdt(char* shmaddr);
返回值:如果失败,则返回-1;
errno=EINVAL(无效的连接地址)
共享内存实例见:shmadd.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#include<stdlib.h>

#define BUFSZ 2048
int main()
{
int shmid;
char *shmadd;
if((shmid=shmget(IPC_PRIVATE,BUFSZ,0666))<0){
perror("shmget");
exit(1);
}
else
printf("created shared-memory:%d/n",shmid);
system("ipcs -m");
if((shmadd=shmat(shmid,0,0))<(char*)0){
perror("shmat");
exit(1);
}
else
printf("attached shared-memory/n");
system("ipcs -m");
if((shmdt(shmadd))<0){
perror("shmdt");
exit(1);
}
else
printf("deleted shared-memory/n");
system("ipcs -m");
exit(0);
}

消息队列
消息队列就是消息的一个链表,它允许一个或多个进程向它写消息,
一个或多个进程从中读消息。具有一定的FIFO的特性,但是可实现消息的随即查询。这些消息存在于内核中,则“队列ID”来标识。消息队列的实现包括创建和打开队列、添加消息、读取消息和控制消息队列这四种操作。
msgget:创建和打开队列,其消息数量受系统限制。
msgsnd:添加消息,将消息添加到消息队列发部。
msgrcv:读取消息,从消息队列中取走消息。
msgctl:控制消息队列。
nt msgget(key_t key,int flag)
key:返回新的或已有队列的ID,IPC_PRIVATE

int msgsnd(int msqid,struct msgbuf *msgp,size_t msgsz,int flag)
其中:msqid是消息队列的队列ID;
msgp是消息内容所在的缓冲区;
msgsz是消息的大小;
msgflag是标志,IPC_NOWAIT若消息并没有立即发送而调用进程会立即
返回。

struct msgbuf{
long mtype;/*type of message*/
char mtext[1];/*message text*/
};
int msgrcv(int msqid,struct msgbuf * msgp,size_t mesgsz,long

msgtyp,int flag)
msqid是消息队列的引用标识符;
msgp是接收到的消息将要存放的缓冲区;
msgsz是消息的大小;
msgtyp是期望接收的消息类型;
msgflag是标志。

int msgctl(int msqid,int cmd,struct msqid_ds*buf)
msqid是消息队列的引用标识符;
cmd是执行命令;
buf是一个缓冲区。
cmd参数指定对于由msqid规定的队列要执行的命令:
IPC_STAT取此队列的msqid_ds结构,并将其存放在buf指向的结构中。
IPC_SET按由buf指向的结构中的值,设置与此队列相关的结构中的下
列四个字段:
msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_qbytes。此命令
只能由下列两种进程执行:一种是其有效用户ID特于msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。只有超级用户才能增加msg_qbytes的值。
IPC_RMID从系统中删除该消息队列以及仍在该队列上的所有数据。这
种删除立即生效。仍在使用这一消息队列的其他进程在它们下一次试图对此队列进行操作进,将出错返回EIDRM。
此命令只能由下列两种进程执行:一种是其有效用户ID等于

msg_perm.cuid或msg_perm.uid;另一种是具有超级用户特权的进程。
消息队列实例见msg.c
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#define BUFSZ 512
struct message{
long msg_type;
char msg_text[BUFSZ];
};
int main(){
int qid;
key_t key;
int len;
struct message msg;
if((key=ftok(".",'a'))==-1){
perror("ftok");
exit(1);
}/*ftok函数学习一下搞明白*/

if((qid=msgget(key,IPC_CREAT|0666))==-1){
perror("msgget");
exit(1);
}

printf("opend queue%d/n",qid);
puts("Please enter the message to queue:");
if((fgets(msg.msg_text,BUFSZ,stdin))==NULL){
puts("no message");
exit(1);
}
msg.msg_type=getpid();
len=strlen(msg.msg_text);
if((msgsnd(qid,&msg,len,0))<0){
perror("message posted");
exit(1);
}
if(msgrcv(qid,&msg,BUFSZ,0,0)<0){
perror("msgrcv");
exit(1);
}

printf("message is%s/n",msg.msg_text);
if((msgctl(qid,IPC_RMID,NULL))<0){
perror("msgctl");
exit(1);
}
exit(0);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值