note
1.使用shmget将在内核创建一个共享内存区
2.使用shmctl才可以删除内核创建的共享内存区
3.使用shmat给当前进程开辟与内核共享内存对应的内存区p,用户态对p的操作会作用到内核共享内存区
code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <time.h>
#include <sys/wait.h>
int shm_id = -1; // 共享内存实例(内核实例),由父进程管理
const size_t shm_len = 1024; // 共享内存字节数
struct mm { // 父子进程通信数据协议
int flag; /* 父进程写状态111 or 子进程读状态222*/
char data[1020];
};
static void remove_shm(void) {
int ret = -1;
if (shm_id != -1) {
fprintf(stdout, "now remove by shm_id\n");
ret = shmctl(shm_id, IPC_RMID, NULL);
if (ret == -1) {
fprintf(stderr, "shmctl error,%s\n", strerror(errno));
}
shm_id = -1;
}
}
int main(int argc, char** argv) {
key_t key = 0;
pid_t pid = 0;
char *pathname = argv[0];
int proj_id = 0x11; // 盐值
struct mm* shm = NULL;
key = ftok(pathname, proj_id); // key由当前程序名和盐值生成
if (key == -1) {
fprintf(stderr, "ftok error,%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
shm_id = shmget(key, shm_len, IPC_CREAT|666);
if (shm_id == -1) {
fprintf(stderr, "shmget error,%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
// 把共享内存映射到当前父进程空间
shm = shmat(shm_id, NULL, 0); // 0:可读可写
if (shm == (void*)(-1)) {
fprintf(stderr, "shmat error,%s\n", strerror(errno));
remove_shm();
exit(EXIT_FAILURE);
}
shm->flag = 111; //父进程先初始化共享内存读写标志
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork error,%s\n", strerror(errno));
shmdt(shm); // 父进程解除共享内存映射
remove_shm(); // 父进程销毁共享内存(内核实例)
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
int i = 0;
shm = shmat(shm_id, NULL, 0); // 把共享内存映射到当前子进程空间
if (shm == (void*)(-1)) {
fprintf(stderr, "fork error,%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; i++) {
if (shm->flag == 222) {
fprintf(stdout, "shm.data:%s", shm->data);
shm->flag = 111;
}
sleep(1);
}
shmdt(shm); // 子进程解除共享内存映射
exit(EXIT_SUCCESS);
}
else if (pid > 0) { // 父进程
int i = 0;
for (i = 0; i < 10; i++) {
if (shm->flag == 111) {
memset(shm->data, 0, shm_len);
time_t t;
time(&t);
sprintf(shm->data, "parent writed to shm,time is %s", ctime(&t));
shm->flag = 222;
}
sleep(1);
}
wait(NULL); // 父进程等待子进程资源回收完成
shmdt(shm); // 父进程解除共享内存映射
remove_shm(); // 父进程删除共享内存实例(内核实例)
exit(EXIT_SUCCESS);
}
return 0;
}