共享内存,消息队列
一:共享内存
共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。共享内存是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递消息。
函数原型为:
#include<sys/shm.h>
1、int shmget(key_t key,size_t size,int shmflg);
作用:新建一块内存或者返回已建好的内存
参数:key,用于表示开辟一段内存,各进程通过这个标志访问同一块内存 size,内存的大小 shmflg,和文件操作完全相同权限表示,按位或IPC_CREATE表示创建一块内存,如果key表示的内存已经建立,即使加了 IPC_CREATE也不会新建一块内存,会返回key关联的内存。
返回值:返回一个标示符,其他对共享内存的操作,用到该返回值
2、void *shmat(int shm_id,const void * shm_addr,int shmflg);
作用:讲一段共享内存连接到当前进程
参数:shm_id,shmget的返回值
shm_addr连接到当前进程的地址位置,一般为NULL,表示让系统来选择
shmfig:SHM_RND,与shm_addr联合使用,控制连接地址
SHM_RDONLY,只读 一般设为0
返回值:指向共享内存第一字节的指针
3、int shmdt(const void * shm_addr);
作用:将共享内存从当前进程分离出去
参数:shmat的返回值
4、int shmctl(int shm_id,int command,struct shmid_ds * buf);
structshmid_ds {
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_prem.mode;
}
作用:对共享内存的控制
参数:shm_id,shm_get的返回值
commond,IPC_STAT:把shmid_ds中的值设为当前共享内存状态值
IPC_SET:把共享内存状态设为shmid_ds中的值
IPC_RMID:删除共享内存段
下面是内存共享实现代码:
申请一块共享内存,往内存里面写数据
1 #include <stdio.h> 2 #include <sys/ipc.h> 3 #include <sys/shm.h> 4 #include <unistd.h> 5 #include <string.h> 6 #include <stdlib.h> 7 8 int main() 9 { 10 int ret = 0; 11 //得到共享内存标识 12 ret = shmget(IPC_PRIVATE, 1, IPC_CREAT); 13 if(ret < 0) { 14 perror("shmget"); 15 exit(EXIT_FAILURE); 16 } 17 printf("ret is %d\n", ret); 18 19 //获取共享内存地址(挂载) 20 char *addr = (char *)shmat(ret, NULL, 0); 21 if(addr == (void *) -1) { 22 perror("shmat"); 23 exit(EXIT_FAILURE); 24 } 25 printf("addr is %p\n", addr); 26 27 char *buf = "hello world bunfly\n"; 28 //向共享内存写数据 29 strcpy(addr, buf); 30 31 //解除关联(卸载) 32 shmdt(addr); 33 34 35 }
读内存里面的数据:
1 #include <stdio.h> 2 #include <sys/ipc.h> 3 #include <sys/shm.h> 4 #include <unistd.h> 5 #include <string.h> 6 #include <stdlib.h> 7 8 int main() 9 { 10 int ret = 950293; 11 char buf[1024] = {0}; 12 13 //获取共享内存地址 (挂载) 14 char *addr = (char *)shmat(ret, NULL, 0); 15 if(addr == (void *) -1) { 16 perror("shmat"); 17 exit(EXIT_FAILURE); 18 } 19 printf("addr is %p\n", addr); 20 21 //从共享内存读数据 22 strcpy(buf, addr); 23 printf("buf is %s\n", buf); 24 25 shmdt(addr); 26 27 //删除共享内存地址 28 if(shmctl(ret ,IPC_RMID,0)==-1) { 29 perror("shmctl"); 30 exit(EXIT_FAILURE); 31 } 32 33 exit(EXIT_SUCCESS); 34 }
二:消息队列
1:int msgget(key_t key, int msgflg);
作用:创建和访问一个消息队列
参数:key,键值表示一个消息队列
msgflg,权限标志位,与shmget标志位类似
返回值:返回一个描述符,用于其他消息队列函数中
2:int msgsnd(int msqid,const void * msg_ptr,size_t msg_sz,int msgflg);
一般把消息用下边结构体表示
struct my_message{
long int message_type;//表示数据类型
/*The data you wish to transfer*/
}
作用:把消息添加到消息队列
参数:msqid,msgget的返回值
msg_ptr,指向准备发送消息的指针
msg_sz,消息长度不包括长整形消息类型变量
msgflg控制当前队列满或达到系统最大限度时发生的事情,一般设为0
3、int msgrcv(int msqid,void * msg_ptr,size_t msg_sz,long intmsgtype,int msgflg);
作用:从消息队列中接收消息
参数:msqid,msgget函数的返回值
msg_ptr,指向准备接收消息的指针
msg_sz,接受消息的大小,不包括表示类型的第一个变量
msgtype,接受类型
msgflg,控制没有消息接收时发生的事情,一般设为0
5、int msgctl(int msqid,int commond,struct msqid_ds * buf);
structmsqid_ds {
uid_t msg_perm.uid;
uid_t msg_perm.gid;
mode_t msg_perm.mode;
}
消息队列实现代码:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/ipc.h> 4 #include <sys/msg.h> 5 int main() 6 { 7 //获得一个消息 8 int ret = 0; 9 ret = msgget(IPC_PRIVATE, IPC_CREAT); 10 if(ret < 0) { 11 perror("msgget"); 12 exit(EXIT_FAILURE); 13 } 14 15 return 0; 16 }
1 #include <stdio.h> 2 #include <sys/ipc.h> 3 #include <sys/msg.h> 4 #include <string.h> 5 #include <stdlib.h> 6 7 struct msgbuf { 8 int type; //数据类型 9 char data[1024]; 10 }; 11 12 int main() 13 { 14 struct msgbuf info; 15 info.type = 1; 16 strcpy(info.data, "hello world"); 17 int id = 32769; 18 19 //添加消息到消息队列 20 int ret = msgsnd(id, &info, sizeof(struct msgbuf), 1); 21 if(ret < 0) { 22 perror("msgsnd"); 23 exit(EXIT_FAILURE); 24 } 25 26 return 0; 27 }
从消息队列接收消息
1 #include <stdio.h> 2 #include <sys/ipc.h> 3 #include <sys/msg.h> 4 #include <stdlib.h> 5 6 int main() 7 { 8 //msgget()函数返回的key值 9 int id = 32769; 10 int ret = 0; 11 char data[1024] = {0}; 12 13 //接收消息 14 ret = msgrcv(id, data, 1028, 1, 1); 15 if(ret < 0) { 16 perror("msgrv"); 17 exit(EXIT_FAILURE); 18 } 19 20 printf("%s\n", data + 4); 21 22 return 0; 23 }