system-V 共享内存

作用

高效率传输大量数据

共享内存用法
  • 定义一个唯一key(ftok)
  • 构造一个共享内存对象(shmget)
  • 共享内存映射(shmat)
  • 解除共享内存映射(shmdt)
  • 删除共享内存(shmctl RMID)
shmget函数

功能:获取共享内存对象的ID

函数原型:

int shmget(key_t key,int size,int shmflg)

参数:

  • key:共享对象键值
  • nsems:共享内存大小
  • shmflg:
    • IPC_CREATE:共享内存不存在则创建
    • mode:共享内存的权限

返回值:

成功:共享内存ID

失败:-1

shmat函数

功能:映射共享内存

函数原型:

int shmat(int shmid,const void *shmaddr,int shmflg)

参数:

  • shmid:共享内存ID
  • shmaddr:映射地址,NULL为自动分配
  • shmflg:
    • SHM_RDONLY:只读方式映射
    • 0:可读可写

返回值:

成功:共享内存首地址

失败:-1

shmdt函数

功能:解除共享内存映射

函数原型:

int shmdt(const void *shmaddr)

参数:

shmaddr:映射地址

返回值:

成功:0

失败:-1

shmctl函数

功能:获取或设置共享内存的相关属性

函数原型:

int shmctl(int shmid,int cmd,struct shmid_ds *buf)

参数:

  • shmid:共享内存ID

  • cmd:

    • IPC_STAT:获取共享内存的属性信息
    • IPC_SET:设置共享内存的属性
    • IPC_RMID:删除共享内存
  • buf:属性缓冲区

返回值:

成功:由cmd类型决定

失败:-1

实现代码
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <wait.h>

#include "sem.h"

int main(void)
{
	char *shm = NULL;//分配的共享内存的原始首地址
	int shmid;//共享内存标识符
    int semid;//信号量标识符
	pid_t pid;

	//创建共享内存
	shmid = shmget((key_t)1234, 4096, 0666 | IPC_CREAT);
	if(shmid == -1)
	{
		fprintf(stderr, "shmget failed\n");
		exit(EXIT_FAILURE);
	}
	
	
	/** 打开信号量,不存在则创建 */
    semid = semget((key_t)6666, 1, 0666|IPC_CREAT); /* 创建一个信号量*/

	if(semid == -1)
	{
		printf("sem open fail\n");
		exit(EXIT_FAILURE); 
	}

	init_sem(semid, 0);
	
	/** 创建一个进程 */
	pid=fork();
	
	if(pid <0 )
	{
		printf("fork fail\n");
		exit(EXIT_FAILURE); 
	}
	
	if(pid==0)
	{
		//子进程
		//将共享内存连接到当前进程的地址空间
		printf("子进程地址开始映射\r\n");
		shm =shmat(shmid, 0, 0);
		if(shm == (void*)-1)
		{
			fprintf(stderr, "shmat failed\n");
			exit(EXIT_FAILURE);
		}
		
		//设置共享内存数据
		memcpy(shm,"hello shm",9);
		printf("正在拷贝\r\n");
		
		sem_v(semid);
		exit(0);
	}
	else
	{
		//父进程
		//阻塞,让子进程先行
		sem_p(semid);
		
		//将共享内存连接到当前进程的地址空间
		printf("父进程地址开始映射\r\n");
		shm =(char*)shmat(shmid, 0, 0);
		if(shm == (void*)-1)
		{
			fprintf(stderr, "shmat failed\n");
			exit(EXIT_FAILURE);
		}
		
		printf("拷贝数据='%s'\r\n",shm);
		
		printf("解除共享内存\r\n");
		if(shmdt(shm) == -1)
		{
			printf("shmdt fail\n");
			exit(EXIT_FAILURE); 
		}
		
		printf("删除共享内存\r\n");
		if(shmctl(shmid,IPC_RMID,NULL) == -1)
		{
			printf("shmdt fail\n");
			exit(EXIT_FAILURE); 
		}
		
		printf("删除信号量\r\n");
		del_sem(semid);
		
		//等待子进程退出
		wait(NULL);
		
		exit(0);
	}	
}
实验现象

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值