Linux共享内存与子进程继承

2022-11-30 16:11:06 浏览数 (1)

总结

  • 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.

0 人点赞