共享内存:
共享内存区是最快的IPC形式,一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程之间的数据交互不再通过内核了。
共享内存示意图:
我们了解了共享内存的示意图,我们再看一下它的代码是怎么样实现的:
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms (与消息队列一样)*/
int shm_segsz; /* size of segment (bytes) */
__kernel_time_t shm_atime; /* last attach time */
__kernel_time_t shm_dtime; /* last detach time */
__kernel_time_t shm_ctime; /* last change time */
__kernel_ipc_pid_t shm_cpid; /* pid of creator */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto - used by DIPC */
void *shm_unused3; /* unused */
};
我们看到结构体的第一个成员还是一个结构体,对比消息队列,都是同一个结构体,可以想到,共享内存也是靠这个结构体进行连接与区别的。
创建和打开共享内存: key--> key_t ftok(const char* pathname,int id)
int shmget(key_t key, //共享内存段名字
size_t size,//想分配多大字节段 ,系统会选择4K的倍数
int shmflg);//IPC_CREAT|0644 0
将共享内存挂载到自己的虚拟地址空间:
void *shmat(int shmid, //id
const void *shmaddr, // NULL
int shmflg); // 0
返回值:返回挂载在虚拟地址空间的起始地址
卸载共享内存段:
int shmdt(const void *shmaddr );//参数是shmat返回的地址
删除共享内存:
ipcrm -M key
int shmctl(id, IPC_RMID,0);
下面是两个进程使用共享内存实现通信:
server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/shm.h>
#include<sys/ipc.h>
int main()
{
key_t key = ftok(".",0x6666); //ipc 键值对
if(key < 0)
{
perror("ftok \n");
return -1;
}
int shmid = 0;
//创建共享内存
shmid = shmget(key,4096,IPC_CREAT|IPC_EXCL|0666);
if(shmid < 0)
{
perror("shmget \n");
return -2;
}
char *addr = shmat(shmid,NULL,0);
sleep(2);
int i = 0;
while(i < 26)
{
printf("client# %s\n",addr);
sleep(1);
i++;
}
shmdt(addr);
sleep(2);
//卸载共享内存
int tmp = 0;
tmp = shmctl(shmid,IPC_RMID,NULL);
if(tmp < 0)
{
perror("shmctl \n");
return -1;
}
return 0;
}
client.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<sys/ipc.h>
int main()
{
key_t key = ftok(".",0x6666);
if(key < 0)
{
perror("ftok \n");
return -1;
}
//获取共享内存
int shmid = shmget(key,4096,IPC_CREAT);
if(shmid < 0)
{
perror("shmget \n");
return -1;
}
//挂载内存
char *addr = shmat(shmid,NULL,0);
sleep(2);
//往共享内存中写东西
int i = 0;
while(i < 26)
{
addr[i] = 'A' + i;
i++;
addr[i] = 0;
sleep(1);
}
//卸载共享内存
int tmp = 0;
tmp = shmdt(addr);
if(tmp < 0)
{
perror("shmctl \n");
return -1;
}
sleep(1);
return 0;
}
效果图:
我们可以通过 ipcs -m 查看系统中有多多少个共享内存:
在程序运行中,再看共享内存
由于共享内存的生命周期随着系统,我们可以在程序中用 shmctl 函数 删除共享内存,
也可以用 ipcrm -m + shmid 指令来删除。
上面就是我对共享内存的总结,希望对在学习的小伙伴有所帮助。