共享内存:共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程
了解命令: ipcs -m:查看系统中有哪些共享内存 ipcs -m shmid:删除系统中的共享内存
步骤方式: 1、创建或者打开共享内存
2、进程A连接(映射)共享内存,写入数据(strcpy()函数)
3、进程A断开
4、进程B连接(映射)共享内存,读取数据
5、进程B断开
6、释放共享内存
函数原型:
#include <sys/shm.h>
// 创建或获取一个共享内存:成功返回共享内存ID,失败返回-1
int shmget(key_t key, size_t size, int flag);
// 连接共享内存到当前进程的地址空间:成功返回指向共享内存的指针,失败返回-1
void *shmat(int shm_id, const void *addr, int flag);
// 断开与共享内存的连接:成功返回0,失败返回-1
int shmdt(void *addr);
// 控制共享内存的相关信息:成功返回0,失败返回-1
int shmctl(int shm_id, int cmd, struct shmid_ds *buf);
1.创建/获取共享内存: shmget函数
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
函数调用成功会返回共享内存标识符,失败返回-1
key:共享内存段的名字,可直接指定,也可通过ftok()函数产生; size:共享内存的大小 ; shmflg:共享内存标记,常取值为IPC_CREAT或IPC_EXCL,单独使用IPC_CREAT时,表示如果共享内存不存在,则创建,如果存在,则打开并返回。但是IPC_EXCL单独使用是没有意义的。通常IPC_CREAT和IPC_EXCL一起使用,表示如果共享内存不存在,则创建,如果存在,则出错,返回。在读取的时候设置成0.
2,连接(映射)共享内存:shmat函数
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
函数调用成功,返回一个指针,指向共享内存的第一个字节;调用失败,返回-1
shmid:共享内存的标识码,shmget()函数的返回值; shmaddr:指定的连接的地址,通常为NULL(取值0),表示系统内核会自动选择一个地址; shmflg:共享内存标记,可能取值为SHM_RND和SHM_RDONLY,表示只读内存,通常为0;
3,断开与共享内存连接:shmdt函数,将共享内存段与当前进程脱离
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
成功返回0,失败返回 -1
shmaddr:shmat()函数返回的地址指针
4,用来控制共享内存:shmdt函数
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
成功返回0,失败返回 -1
shmid:共享内存的标识码,shmget()函数的返回值; cmd:有3个可取值,一般使用IPC_RMID; buf:结构体指针,表示向共享内存发送命令的参数,一般不关心,取值为0;
cmd参数的可取值: IPC_STAT :把shmid_ds结构中的数据设置为共享内存的当前关联值 IPC_SET :进程有足够权限的前提下,把共享内存的当前关联值设置为shmid_ds结构中给出的 IPC_RMID:删除共享内存段---一般设置成这个
函数例子:
写入数据:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int shmid; //共享内存标识符
char *shmaddr;
key_t key;
key = ftok(".",1); //获取键值
shmid = shmget(key,1024*4,IPC_CREAT|0666); //打开或者创建共享内存
if(shmid == -1){
printf("shmget NO OK\n");
exit(-1);
}
shmaddr = shmat(shmid,0,0); //共享内存连接到当前进程的地址空间
printf("shmat ok\n");
strcpy(shmaddr,"hello world"); //向内存中写入数据
sleep(5); //睡眠5秒,等待内存数据被读走
shmdt(shmaddr); //断开进程和内存的连接
shmctl(shmid,IPC_RMID,0); //删除共享内存段
printf("quit\n");
return 0;
}
读取数据:
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int shmid;
char *shmaddr;
key_t key;
key = ftok(".",1); //获取键值
shmid = shmget(key,1024*4,0); //打开创建的共享内存,只读取,最后一个参数设置成0
if(shmid == -1){
printf("shmget no ok\n");
exit(-1);
}
shmaddr = shmat(shmid,0,0); //共享内存连接到当前进程的地址空间
printf("shmat ok\n"); //表示连接成功
printf("data : %s",shmaddr); //将内存地址中的数据读出,打印
shmdt(shmaddr); //断开内存和当前进程的连接
printf("quit\n");
return 0;
}