共享内存是常用的进程间通信,两个进程可以直接共享访问同一块内存区域。
实现共享内存的步骤如下:
(1) 创建内存共享区
进程1通过操作系统提供的api从内存中申请一块共享区域,linux系统中可以通过shmget函数实现,生成的共享内存块与某个特定的key进行绑定。
(2) 映射共享内存到进程1中
在linux环境中,可以通过shmat实现。
(3)映射共享内存到进程2中
进程2通过进程1的shmget函数和同一个key值,然后执行shmat,将这个内存映射到进程2中。
(4)进程1与进程2中相互通信
共享内存实现两个映射后,可以利用该区域进行信息交换,由于没有同步机制,需要参与通信的进程自己协商处理。
(5)撤销内存映射关系
完成通信之后,需要撤销之前的映射操作,通过shmdt函数实现。
(6)删除共享内存区
在linux中通过shctl函数来实现。
以下为举例实现调用linux系统提供的相关函数。
* One shmid data structure for each shared memory segment in the system. */ struct shmid_ds { struct ipc_perm shm_perm; /* operation perms */ int shm_segsz; /* size of segment (bytes) */ time_t shm_atime; /* last attach time */ time_t shm_dtime; /* last detach time */ time_t shm_ctime; /* last change time */ unsigned short shm_cpid; /* pid of creator */ unsigned short shm_lpid; /* pid of last operator */ short shm_nattch; /* no. of current attaches */ /* the following are private */ unsigned short shm_npages; /* size of segment (pages) */ unsigned long *shm_pages; /* array of ptrs to frames -> SHMMAX */ struct vm_area_struct *attaches; /* descriptors for attaches */ };
(1) test1.c
/*
* 共享内存中几个常见函数呢的使用
* shmget, shmat, shmdt, shmctl
*/
#include <stdio.h>
#include <unistd.h> // getpagesize()
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#define SHARE_MEMORY_KEY 674
int main() {
// 获取系统中页面的大小,
printf("page size = %d\n", getpagesize());
int shareMemoryId, ret;
// 创建页面大小的共享内存区段
shareMemoryId = shmget(SHARE_MEMORY_KEY, getpagesize(), 0666|IPC_CREAT);
if (shareMemoryId > 0)
printf("Create a shared memory segment %d\n", shareMemoryId);
// 共享内存区段的挂载
void* mem;
mem = shmat(shareMemoryId, (const void *)0, 0);
// 获取一个内存区段的信息
struct shmid_ds shmds;
ret = shmctl(shareMemoryId, IPC_STAT, &shmds);
if (ret == 0) {
printf("Size of memory segment is %d bytes.\n", (int) shmds.shm_segsz);
printf("Number of attach %d\n", (int) shmds.shm_nattch);
} else
printf("shmctl() call failed.\n");
// 共享内存区段的脱离
ret = shmdt(mem);
if (ret == 0)
printf("Successfully detach memory.\n");
else
printf("Memory detached failed %d\n", errno);
// 删除该共享内存区
ret = shmctl(shareMemoryId, IPC_RMID, 0);
if (ret == 0)
printf("Share memory removed.\n");
else
printf("Share memory remove failed.\n");
return 0;
}
输出:
wang@wang:~/test/test6$ ./a.out
page size = 4096
Create a shared memory segment 4751390
Size of memory segment is 4096 bytes.
Number of attach 1
Successfully detach memory.
Share memory removed.