消息队列

消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列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;
}