目录
前言
共享内存区别于管道,是最快的进程间通信方式,不需要对数据进行拷贝就可以实现数据交换。不同进程将共享内存链接到各自的空间,所有链接了这块共享内存的进程都可以共同访问这个共享内存中的数据。
另外一题,共享内存没有同步机制,而管道具有同步机制。
共享内存
作用:实现多个进程间的数据共享
特性:最快的进程间通信,生命周期不随进程而是随内核(不会因为进程退出而释放)
原理:开辟一块物理内存,多个进程将这块内存映射到自己的虚拟地址,然后可以通过虚拟地址访问这块共享内存
接口
shmget
① int shmget(key_t key,size_t size,int shmflg);创建共享内存
key:共享内存标识符(名字),key的值为IPC_PRIVATE时表示系统每次都会申请一个新的标识符。
size:共享内存大小
shmflg:权限标志,常用有IPC_CREAT和 IPC_EXCL ,后面再加权限
IPC_CREAT —— 共享内存不存在时创建共享内存,存在则打开
IPC_EXCL —— 与IPC_CREAT共同使用,不存在时创建,存在则报错
例如:IPC_CREAT | IPC_EXCL | 0644
返回值:成功返回操作句柄,失败返回-1。
代码示例
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdlib.h>
int main(){
int shmid = shmget(IPC_PRIVATE,4096,IPC_CREAT|0644);
if(shmid<0){
printf("shmget failed!\n");
exit(-1);
}else{
printf("shmid=%d\n",shmid);
}
return 0;
}
shmat
② void* shmat(int shmid,void *addr,int shmflg); 链接共享内存
shmid:打开一个共享内存时返回的操作句柄
addr:映射首地址,通常置为NULL,来让系统进行分配
shmflg:默认为0,表示可读可写,置为SHM_RDONLY表示只读
返回值:成功时返回映射首地址,失败返回-1。
shmdt
③ int shmdt(const void *shmaddr); 解除与共享内存的映射关系
shmaddr是映射的首地址,也就是shmat的返回值
shmctl
④ int shmctl(int shmid,int cmd,struct shmid_ds *buf); 可用于删除共享内存
shmid:是shmget返回的句柄
cmd:要进行的操作,值为IPC_RMID时表示标记一个共享内存需要被删除
buf:用于设置或获取共享内存信息,如果cmd是IPC_RMID,则buf被忽略,删除时置NULL
注意:shmctl在删除一块共享内存时不会立刻删除,而是先阻断链接(后来的进程无法链接),等连接数为0后(已经链接的进程全退出后)再执行删除。
ipcs -m 指令
该指令可用于查看共享内存的信息
ipcrm -m shmid 指令
该指令可在程序外面手动删除共享内存,因为有些时候我们在运行程序时会ctrl+c暂停,或是遇到其他意外导致之前创建的共享内存没能被及时删除,此时如果需要删除就可以用这个指令,当然重新开机也可以清除所有的共享内存。
上面的nattch是连接数
代码示例
注意shmat和shmdt要一起使用才起作用
#include <stdio.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(){
int shmid = shmget(IPC_PRIVATE,4096,IPC_CREAT | 0666);
if(shmid<0){
printf("shmget failed!\n");
exit(-1);
}else{
printf("shmid=%d\n",shmid);
}
char *str = (char*)shmat(shmid,NULL,0);//链接shmid的共享内存
if(str<0){
printf("connection failed!\n");
exit(-1);
}else{
printf("连接成功\n");
}
shmdt(str);//删除链接
shmctl(shmid,IPC_RMID,0);//删除共享内存
return 0;
}