共享内存
共享存储允许两个或多个进程共享一给定的存储区。
因为数据不需要在客户机和服务器之间复制。
这是比较老的 IPC 机制。
查看共享内存,shell命令
ipcs
函数
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
#include <sys/shm.h>
#include <sys/ipc.h>
int shmget(key_t key, size_t size, int shmflg);
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
ftok()
- 生成key,pathname必须调用进程可以访问的。
- proj_id必须有效。
shmget()
- 它获得一个指定大小的共享存储标识符。
- key参数用来标识共享内存,size参数该共享存储段的最小值,如果正在创建一个新段(一般在服务器中),则必须指定其size。如果正在访问一个现存的段(一个客户机),则将size指定为0.
- shmfig参数有IPC_CREAT 和 IPC_EXCL,最为重要的是shmfig中指定访问权限,跟open的mode参数一样,否则会出现permission denied等错误。
- 返回值:若成功则共享内存ID,若出错为-1.
流程
- ftok(“./temp”, 0) 申请一个key_t。
- shmget(key)获取共享内存对应的id,如果共享内存未创建,通过flag参数创建此共享内存。
- shmat(id)挂载共享内存,返回地址address
- 使用该内存address
- shmdt(id)卸载共享内存
- shmctl()删除共享内存
删除共享内存
ipsrm -m shmid号
代码
/*************************************************************************
> File Name: shm.c
> Author:
> Mail:
> Created Time: Sat 29 Jan 2022 03:45:09 PM CST
************************************************************************/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
int main() {
key_t key = ftok("./t.txt", 123);
if (key < 0) {
perror("ftok");
exit(1);
}
printf("key = ox%x\n", key);
int shmid = shmget(key, 20, /*IPC_EXCL |*/ IPC_CREAT | 0644);
if (shmid < 0) {
perror("shmget");
exit(1);
}
printf("shmid = %d\n", shmid);
//把内核开辟的空间挂载到用户空间
void* tp_shmp = shmat(shmid, NULL, 0); //返回地址
if (tp_shmp < 0) {
perror("shmat");
exit(1);
}
printf("shmp = %p\n", tp_shmp);
char* shmp = (char*)tp_shmp;
memset(shmp, 0, 20);
// sprintf(shmp, "344jfvsdbfb十多个好好减肥djkfvhkjdbfskdhkjsdhfjksdh\n");
pid_t pd = fork();
if (pd < 0) {
perror("fork");
exit(1);
}
if (pd == 0) {
//子进程读共享内存
printf("我来了!\n");
while (1) {
sleep(1);
if (strcmp(shmp, "quit") == 0) break;
if (*shmp) {
printf("读到:%s\n", shmp);
memset(shmp, 0, 20);
}
}
printf("我走了!\n");
} else {
printf("我开始写了!\n");
while (1) {
scanf("%s", shmp);
if (strcmp(shmp, "quit") == 0) break;
}
printf("你咋还没死!\n");
wait(NULL); //阻塞等待子进程死
printf("你死了!\n");
}
//取消挂载
shmdt(shmp);
return 0;
}