总结
- Postgresql使用mmap创建匿名内存块作为共享内存使用。
- Postgresql也会使用system v的接口申请ipc共享内存(本篇)。
目前PG15中只有这一个变量会放在ipc的共享内存中了,其他都在mmap申请的匿名块中。
代码语言:javascript复制typedef struct PGShmemHeader /* standard header for all Postgres shmem */
{
int32 magic; /* magic # to identify Postgres segments */
#define PGShmemMagic 679834894
pid_t creatorPID; /* PID of creating process (set but unread) */
Size totalsize; /* total size of segment */
Size freeoffset; /* offset to first free space */
dsm_handle dsm_control; /* ID of dynamic shared memory control seg */
void *index; /* pointer to ShmemIndex table */
#ifndef WIN32 /* Windows doesn't have useful inode#s */
dev_t device; /* device data directory is on */
ino_t inode; /* inode number of data directory */
#endif
} PGShmemHeader;
- IPC的共享内存使用分为三步:
- 申请:shm_id申请共享内存段,申请后可以使用ipcs -m查询
- 关联:shmat将共享内存映射到自己的内存空间中
- 解除关联:shmdt将共享内存映射删除
- 释放:shmctl IPC_RMID删除共享内存段
- IPC申请的共享内存关联后可以拿到映射地址,映射地址子进程可以直接使用。
IPC的共享内存实例1
代码语言:javascript复制#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#define IPCProtection (0600) /* access/modify by user only */
int main(void)
{
int shm_id;
char *memAddress;
struct shmid_ds shmbuffer;
/* $PGDATA */
char *DataDir = "/tmp/s1";
struct stat statbuf;
stat(DataDir, &statbuf);
shm_id = shmget(statbuf.st_ino, 1073741824, IPC_CREAT | IPC_EXCL | IPCProtection);
printf("shared memory key: %ldn", statbuf.st_ino);
/* attaches System V shared memory segment */
memAddress = (char *)shmat(shm_id, 0, 0);
printf("shared memory attached at address %pn", memAddress);
shmctl(shm_id, IPC_STAT, &shmbuffer);
printf("segment size:%ldn", shmbuffer.shm_segsz);
sprintf(memAddress, "Hello,world.");
/* detaches */
shmdt(memAddress);
/* attaches System V shared memory segment */
memAddress = (char *)shmat(shm_id, (void *)0x500000, 0);
printf("shared memory reattched at address %pn", memAddress);
printf("%sn", memAddress);
shmdt(memAddress);
/* release shared memory segment */
shmctl(shm_id, IPC_RMID, 0);
return 0;
}
// gcc -o main1 -Wall -g -ggdb -O0 -g3 -gdwarf-2 main1.c
执行结果:
代码语言:javascript复制shared memory key: 527687
shared memory attached at address 0x7fb7253e1000
segment size:1073741824
shared memory reattched at address 0x500000
Hello,world.
IPC的共享内存实例2:子进程
代码语言:javascript复制#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define IPCProtection (0600) /* access/modify by user only */
int main(void)
{
int shm_id;
char *memAddress;
struct shmid_ds shmbuffer;
/* $PGDATA */
char *DataDir = "/tmp/s1";
struct stat statbuf;
stat(DataDir, &statbuf);
shm_id = shmget(statbuf.st_ino, 1073741824, IPC_CREAT | IPC_EXCL | IPCProtection);
printf("shared memory key: %ldn", statbuf.st_ino);
/* attaches System V shared memory segment */
memAddress = (char *)shmat(shm_id, 0, 0);
printf("shared memory attached address %pn", memAddress);
shmctl(shm_id, IPC_STAT, &shmbuffer);
printf("segment size:%ldn", shmbuffer.shm_segsz);
/* fork */
pid_t pid = fork();
if (pid > 0)
{
sprintf(memAddress, "Hello child.");
wait(NULL);
printf("%sn", (char *)memAddress);
}
else if (pid == 0)
{
printf("%sn", (char *)memAddress);
sprintf(memAddress, "Hello parent.");
}
/* release shared memory segment */
shmctl(shm_id, IPC_RMID, 0);
return 0;
}
// gcc -o main2 -Wall -g -ggdb -O0 -g3 -gdwarf-2 main2.c
执行结果
代码语言:javascript复制shared memory key: 527687
shared memory attached address 0x7f79de044000
segment size:1073741824
Hello child.
Hello parent.