note
1.shm_open的pathname不能带路径名,shm_open的创建目录为/dev/shm
2.使用ftruncate设置内核共享内存实例的大小
3.使用mmap进行有名映射(实例反应在文件系统的一个文件)
code
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/types.h>
#define PARENT_WRITABLE 111
#define CHILD_READABLE 222
typedef struct proto_data {
int flag;
char text[1020];
}proto_data_t;
int main(int argc, char** argv) {
int shm_id = -1;
const char* shm_obj = "shm_obj"; /* shm_open的pathname不能带路径名,shm_open的创建目录为/dev/shm */
pid_t pid = 0;
void* pMem = NULL;
int ret = -1;
// 父进程创建共享内存实例(位于内核)
shm_id = shm_open(shm_obj, O_CREAT|O_RDWR, S_IRWXU|S_IRGRP|S_IROTH);
if (shm_id == -1) {
fprintf(stderr, "shm_open error,%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "shm_open success,shm_id:%d\n", shm_id);
// 设置共享内存的大小
ret = ftruncate(shm_id, sizeof(proto_data_t));
if (ret == -1) {
fprintf(stderr, "ftruncate error,%s\n", strerror(errno));
shm_unlink(shm_obj); // 删除内核的共享内存实例
exit(EXIT_FAILURE);
}
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork error,%s\n", strerror(errno));
shm_unlink(shm_obj); // 删除内核的共享内存实例
exit(EXIT_FAILURE);
}
fprintf(stdout, "fork success\n");
if (pid == 0) { // child
int i = 0;
proto_data_t* data = NULL;
pMem = mmap(NULL, sizeof(proto_data_t), PROT_READ|PROT_WRITE, MAP_SHARED, shm_id, 0); // 内存映射
if (pMem == MAP_FAILED) {
fprintf(stderr, "child process mmap error,%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stdout, "child mmap success\n");
data = pMem;
for (int i = 0; i < 10; ++i) {
fprintf(stdout, "child process in loop\n");
if (data->flag == CHILD_READABLE) {
fprintf(stdout, "child read:%s\n", data->text);
data->flag = PARENT_WRITABLE;
}
sleep(1);
}
munmap(pMem, sizeof(proto_data_t)); // 解除内存映射
exit(EXIT_SUCCESS);
}
else if (pid > 0) { // parent
int i = 0;
proto_data_t* data = NULL;
time_t t = 0;
pMem = mmap(NULL, sizeof(proto_data_t), PROT_READ|PROT_WRITE, MAP_SHARED, shm_id, 0); // 内存映射
if (pMem == MAP_FAILED) {
fprintf(stderr, "parent process mmap error,%s\n", strerror(errno));
shm_unlink(shm_obj); // 父进程删除内核的共享内存实例
exit(EXIT_FAILURE);
}
fprintf(stdout, "parent mmap success\n");
data = pMem;
data->flag = PARENT_WRITABLE;
fprintf(stdout, "parent data->flag set success\n");
for (int i = 0; i < 10; ++i) {
fprintf(stdout, "parent process in loop\n");
if (data->flag == PARENT_WRITABLE) {
memset(data->text, 0, sizeof(data->text));
time(&t);
sprintf(data->text, "writen by parent,%s", ctime(&t));
data->flag = CHILD_READABLE;
}
sleep(1);
}
wait(NULL); // 回收子进程资源
munmap(pMem, sizeof(proto_data_t)); // 解除内存映射
shm_unlink(shm_obj); // 父进程删除内核的共享内存实例
exit(EXIT_SUCCESS);
}
return 0;
}