mmap(内存映射)和shm(共享存储):
1、mmap是在磁盘上建立一个文件,每个进程地址空间中开辟出一块空间进行映射。
而对于shm而言,shm每个进程最终会映射到同一块物理内存。
shm保存在物理内存,这样读写的速度要比磁盘要快,但是存储量不是特别大。
2、相对于shm来说,mmap更加简单,调用更加方便,所以这也是大家都喜欢用的原因。
3、另外mmap有一个好处是当机器重启,因为mmap把文件保存在磁盘上,这个文件还保存了操作系统同步的映像,所以mmap不会丢失,但是shmget就会丢失
$ -> g++ shmread.cpp -o read -lpthread
$ -> g++ shmwrite.cpp -o write -lpthread
$ -> ./read
READ PROCESS:
OK
READ PROCESS:
GOOD
READ PROCESS:
BYE
READ PROCESS:
exit
$ -> ./write
WRITE PROCESS:
OK
WRITE PROCESS:
GOOD
WRITE PROCESS:
BYE
WRITE PROCESS:
exit
(1)shminfo.h
#ifndef SHARE_MEMORY_INFO_H
#define SHARE_MEMORY_INFO_H
#include
#define SHM_MODE 0666
#define SEM_NAME "/shmtest_sem"
#define CHECK_ERROR(flag, funname) do { \
bool tmp = (flag); \
if (tmp) { \
printf("%s return error", funname); \
} \
} while (0)
struct shm_data
{
char data[32];
int len;
};
#endif
(2)shmread.cpp
#include
#include
#include
#include
#include "shminfo.h"
#include
#include
#include
#include
int main()
{
key_t key;
shm_data *shm = NULL; // share info
sem_t *sem = NULL;
int shmid;
sem = sem_open(SEM_NAME, O_CREAT, SHM_MODE, 1);
CHECK_ERROR(SEM_FAILED == sem, "sem_open");
key =ftok(".", 1);
CHECK_ERROR(-1 == key, "ftok");
shmid = shmget(key, sizeof(shm_data), SHM_MODE | IPC_CREAT);
CHECK_ERROR(-1 == shmid, "shmget");
shm = (shm_data *)shmat(shmid, NULL, 0);
CHECK_ERROR((shm_data *)-1 == shm, "shmat");
for (;;) {
CHECK_ERROR(-1 == sem_wait(sem), "sem_wait");
printf("READ PROCESS:\n %s", shm->data);
sleep(rand()%5);
if (0 == strcmp(shm->data, "exit\n")) {
printf("goodbye read\n");
fflush(stdout);
sem_post(sem);
break;
}
sem_post(sem);
sleep(rand()%5);
}
if (NULL != sem) {
CHECK_ERROR(-1 == sem_close(sem), "sem_close");
CHECK_ERROR(-1 == sem_unlink(SEM_NAME), "sem_unlink"); // sem instance stores in "/dev/shm/", recreated will fail, if no unlink
}
if (NULL != shm) {
CHECK_ERROR(-1 == shmdt(shm), "shmdt"); // detach share memory from current process
CHECK_ERROR(-1 == shmctl(shmid, IPC_RMID, 0), "shmctl");// delete share memory
}
return 0;
}
(3)shmwrite.cpp
#include
#include
#include
#include
#include "shminfo.h"
#include
#include
#include
#include
int main()
{
key_t key;
shm_data *shm = NULL; // share info
sem_t *sem = NULL;
int shmid;
sem = sem_open(SEM_NAME, O_CREAT, SHM_MODE, 1);
CHECK_ERROR(SEM_FAILED == sem, "sem_open");
key =ftok(".", 1);
CHECK_ERROR(-1 == key, "ftok");
shmid = shmget(key, sizeof(shm_data), SHM_MODE | IPC_CREAT);
CHECK_ERROR(-1 == shmid, "shmget");
shm = (shm_data *)shmat(shmid, NULL, 0);
CHECK_ERROR((shm_data *)-1 == shm, "shmat");
for (;;) {
CHECK_ERROR(-1 == sem_wait(sem), "sem_wait");
printf("WRITE PROCESS:\n");
fgets(shm->data, 32, stdin);
if (0 == strcmp(shm->data, "exit\n")) {
printf("goodbye write\n");
fflush(stdout);
sem_post(sem);
break;
}
sem_post(sem);
sleep(rand()%6);
}
if (NULL != sem) {
sem_close(sem);
}
if (NULL != shm) {
CHECK_ERROR(-1 == shmdt(shm), "shmdt"); // detach share memory from current process
}
return 0;
}