• Linux共享内存与子进程继承


    总结

    • Postgresql使用mmap创建匿名内存块作为共享内存使用。
    • Postgresql也会使用system v的接口申请ipc共享内存(本篇)。

    目前PG15中只有这一个变量会放在ipc的共享内存中了,其他都在mmap申请的匿名块中。

    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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • IPC的共享内存使用分为三步:

      • 申请:shm_id申请共享内存段,申请后可以使用ipcs -m查询
      • 关联:shmat将共享内存映射到自己的内存空间中
      • 解除关联:shmdt将共享内存映射删除
      • 释放:shmctl IPC_RMID删除共享内存段
    • IPC申请的共享内存关联后可以拿到映射地址,映射地址子进程可以直接使用。

    IPC的共享内存实例1

    #include 
    #include 
    #include 
    #include 
    #include 
    
    #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: %ld\n", statbuf.st_ino);
    
    	/* attaches System V shared memory segment */
    	memAddress = (char *)shmat(shm_id, 0, 0);
    	printf("shared memory attached at address %p\n", memAddress);
    
    	shmctl(shm_id, IPC_STAT, &shmbuffer);
    	printf("segment size:%ld\n", 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 %p\n", memAddress);
    	printf("%s\n", 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    执行结果:

    shared memory key: 527687
    shared memory attached at address 0x7fb7253e1000
    segment size:1073741824
    shared memory reattched at address 0x500000
    Hello,world.
    
    • 1
    • 2
    • 3
    • 4
    • 5

    IPC的共享内存实例2:子进程

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #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: %ld\n", statbuf.st_ino);
    
    	/* attaches System V shared memory segment */
    	memAddress = (char *)shmat(shm_id, 0, 0);
    	printf("shared memory attached address %p\n", memAddress);
    
    	shmctl(shm_id, IPC_STAT, &shmbuffer);
    	printf("segment size:%ld\n", shmbuffer.shm_segsz);
    
    	
    
    	/* fork */
    	pid_t pid = fork();
    	if (pid > 0)
    	{
    		sprintf(memAddress, "Hello child.");
    		wait(NULL);
    		printf("%s\n", (char *)memAddress);
    	}
    	else if (pid == 0)
    	{
    		printf("%s\n", (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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    执行结果

    shared memory key: 527687
    shared memory attached address 0x7f79de044000
    segment size:1073741824
    Hello child.
    Hello parent.
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    多御安全浏览器新版下载 | 功能优秀性能出众
    centos6服务器升级glibc失败后操作系统命令不能执行处理
    MIT 6.858 计算机系统安全讲义 2014 秋季(二)
    C/C++:[Error] ld returned 1 exit status 解决方案
    sftp文件上传uploadFile
    Spring之AOP动态代理
    Pandas数据分析2-数据分组、Apply函数、合并
    你绝对需要的Facebook养号攻略,教你如何养成耐用号
    Spring中ApplicationListener事件监听机制详解
    计算机毕业设计springboot+vue大学生个人财务管理系统
  • 原文地址:https://blog.csdn.net/jackgo73/article/details/128021947