消息队列
消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
1、特点
消息队列是面向记录的,其中的消息具有特定的格式以及特定的优先级。
消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
消息队列可以实现消息的随机查询,消息不一定要以先进先出的次序读取,也可以按消息的类型读取
消息队列通信原理
有A,B两个进程
1.创建或获取队列
2.A进程往队列里写消息
3.B进程往队列里读消息
4.删除队列
(反之也一样)
1 #include <sys/msg.h>
2 // 创建或打开消息队列:成功返回队列ID,失败返回-1
3 int msgget(key_t key, int flag);
4 // 添加消息:成功返回0,失败返回-1
5 int msgsnd(int msqid, const void *ptr, size_t size, int flag);
6 // 读取消息:成功返回消息数据的长度,失败返回-1
7 int msgrcv(int msqid, void *ptr, size_t size, long type,int flag);
8 // 控制消息队列:成功返回0,失败返回-1
9 int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msg_send;
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
#include <unistd.h>
#include<stdlib.h>
//int msgget(key_t key, int msgflg);
// key_t ftok(const char *pathname, int proj_id);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
// ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
key_t key;
struct msgbuf msg={888,"hello msg"};
struct msgbuf readbuf;
key=ftok(".",'z');
if(key==-1){
printf("creat key failed\n");
exit(-1);
}
int msgId=msgget(key,IPC_CREAT|0777);
if(msgId!=-1){
printf("creat msg success\n");
}
for(int i=0;i<10;i++){
int ret=msgsnd(msgId,&msg,strlen(msg.mtext),0);
sleep(1);
if(ret!=-1){
printf("msgsnd success\n");
}
int msgSize=msgrcv(msgId,&readbuf,sizeof(readbuf.mtext),988,0);
sleep(1);
if(msgSize!=-1){
printf("read:%d,context:%s\n",msgSize,readbuf.mtext);
}
}
int ret1=msgctl(msgId,IPC_RMID,NULL);
if(ret1!=-1){
printf("delete success\n");
}
return 0;
}
msg_get
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<string.h>
#include <unistd.h>
#include<stdlib.h>
//int msgget(key_t key, int msgflg);
// key_t ftok(const char *pathname, int proj_id);
// int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
// ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
struct msgbuf {
long mtype; /* message type, must be > 0 */
char mtext[128]; /* message data */
};
int main()
{
key_t key;
struct msgbuf readbuf={988,"hello xxx"};
struct msgbuf msg;
key=ftok(".",'z');
if(key==-1){
printf("creat key failed\n");
exit(-1);
}
int msgId=msgget(key,IPC_CREAT|0777);
if(msgId!=-1){
printf("creat msg success\n");
}
for(int i=0;i<10;i++){
int msgSize=msgrcv(msgId,&msg,sizeof(msg.mtext),888,0);
sleep(1);
if(msgSize!=-1){
printf("read:%d,context:%s\n",msgSize,msg.mtext);
}
int ret=msgsnd(msgId,&readbuf,strlen(readbuf.mtext),0);
sleep(1);
if(ret!=-1){
printf("msgsnd success\n");
}
}
int ret1=msgctl(msgId,IPC_RMID,NULL);
if(ret1!=-1){
printf("delete success\n");
}
return 0;
}
共享内存
共享内存(Shared Memory),指两个或多个进程共享一个给定的存储区。
1、特点
共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
因为多个进程可以同时操作,所以需要进行同步。
信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
通信原理:
1.打开或创建共享内存
2.映射
3.数据交换
4.释放内存
5.删除共享内存
当用shmget函数创建一段共享内存时,必须指定其 size;而如果引用一个已存在的共享内存,则将 size 指定为0 。
当一段共享内存被创建以后,它并不能被任何进程访问。必须使用shmat函数连接该共享内存到当前进程的地址空间,连接成功后把共享内存区对象映射到调用进程的地址空间,随后可像本地空间一样访问。
shmdt函数是用来断开shmat建立的连接的。注意,这并不是从系统中删除该共享内存,只是当前进程不能再访问该共享内存而已。
shmctl函数可以对共享内存执行多种操作,根据参数 cmd 执行相应的操作。常用的是IPC_RMID(从系统中删除该共享内存)。
函数原型:
1 #include <sys/shm.h>
2 // 创建或获取一个共享内存:成功返回共享内存ID,失败返回-1
3 int shmget(key_t key, size_t size, int flag);
4 // 连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1
5 void *shmat(int shm_id, const void *addr, int flag);
6 // 断开与共享内存的连接:成功返回0,失败返回-1
7 int shmdt(void *addr);
8 // 控制共享内存的相关信息:成功返回0,失败返回-1
9 int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
shm_send
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include<stdlib.h>
#include<string.h>
#include <unistd.h>
//int shmget(key_t key, size_t size, int shmflg);
//void *shmat(int shmid, const void *shmaddr, int shmflg);
//int shmdt(const void *shmaddr);
// int shmctl(int shmid, int cmd, struct shmid_ds *buf);
int main()
{
char *shmaddr;
key_t key;
key=ftok(".",'z');
if(key!=-1){
printf("key=%d\n",key);
}
int shmid=shmget(key,1024*4,IPC_CREAT|0777);
if(shmid!=-1){
printf("creat shmid success\n");
}
shmaddr=shmat(shmid,0,0);
if(shmaddr>0){
printf("shmat ok\n");
}
for(int i=0;i<10;i++){
strcpy(shmaddr,"xiewenhui");
sleep(1);
}
int ret=shmdt(shmaddr);
if(ret==-1){
printf("shmdt failed\n");
exit(-1);
}
return 0;
}
shm_get
#include<stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include<stdlib.h>
#include <unistd.h>
//int shmget(key_t key, size_t size, int shmflg);
//void *shmat(int shmid, const void *shmaddr, int shmflg);
//int shmdt(const void *shmaddr);
// int shmctl(int shmid, int cmd, struct shmid_ds *buf);
int main()
{
char *shmaddr;
key_t key;
key=ftok(".",'z');
if(key!=-1){
printf("key=%d\n",key);
}
int shmid=shmget(key,1024*4,0);
if(shmid!=-1){
printf("creat shmid success\n");
}
shmaddr=shmat(shmid,0,0);
if(shmaddr>0){
printf("shmat ok\n");
}
for(int i=0;i<10;i++){
printf("data:%s\n",shmaddr);
sleep(1);
}
int ret=shmdt(shmaddr);
if(ret==-1){
printf("shmdt failed\n");
exit(-1);
}
int ret1=shmctl(shmid,IPC_RMID,NULL);
if(ret1==-1){
printf("shmctl failed\n");
exit(-1);
}
return 0;
}