Linux进程间通信之mmap(六)

1.mmap原理

存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。于是当从缓冲区中取数据,就相当于读文件中的相应字节。于此类似,将数据存入缓冲区,则相应的字节就自动写入文件。这样,就可在不适用read和write函数的情况下,使用地址(指针)完成I/O操作。 使用存储映射这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap函数来实现。

2.Mmap映射

在这里插入图片描述

3.mmap使用

3.1.建立映射区

	void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

功能:
建立映射区。

参数:
addr:地址,填NULL。
length:长度,要申请的映射区的长度。
prot:权限。PROT_READ 可读 ; PROT_WRITE 可写。
flags: 标志位。MAP_SHARED 共享的 – 对映射区的修改会影响源文件; MAP_PRIVATE 私有的。
fd:文件描述符,需要打开一个文件。
offset:指定一个偏移位置 ,从该位置开始映射 。

返回值:
成功:返回映射区的首地址
失败:返回 MAP_FAILED ((void *) -1)

3.2.建立映射区

	int munmap(void *addr, size_t length);

功能:
释放映射区。

参数:
addr:映射区的首地址。
length:映射区的长度。

返回值:
成功:返回0
失败:返回 -1

4.参考代码

4.1.使用共享内存映射实现两个进程之间的通信

(1)A进程

//=============================================================================
// File Name    : process_mmap_communication_A.c
// Author       : FengQQ
//
// Description  : 使用共享内存映射实现两个进程之间的通信
// Annotation   : 两个程序映射到同一个文件到自己的地址空间,进程A先运行,
//				  每个两秒读取映射区域,看是否发生变化,进程B后运行,
//                它修改映射区域,然后退出,此时进程A能够观察到存储映射区的变化
//
// Created by FengQQ. 2020-10-02
//=============================================================================

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>

int main(int argc,char *argv[])
{
	
	int fd;
	int ret;
	struct stat sb;
	char *mapped;
	
	fd = open(argv[1],O_RDWR);				//打开文件
	if(fd < 0)
	{
		printf("open failed...\r\n");
	}
	
	ret = fstat(fd,&sb);					//获取文件的属性
	if(ret < 0)
	{
		printf("fstat failed...\r\n");
	}
	
	//将文件映射至进程的地址空间
	mapped = (char *)mmap(NULL,sb.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(mapped < 0)
	{
		printf("mmap failed...\r\n");
	}
	
	close(fd);								//文件已在内存, 关闭文件也可以操纵内存   

	while(1)	
	{
		printf("%s\r\n",mapped);			//每隔两秒查看存储映射区是否被修改
		sleep(2);
	}
	
	return 0;
}

(2)B进程

//=============================================================================
// File Name    : process_mmap_communication_B.c
// Author       : FengQQ
//
// Description  : 使用共享内存映射实现两个进程之间的通信
// Annotation   : 两个程序映射到同一个文件到自己的地址空间,进程A先运行,
//				  每个两秒读取映射区域,看是否发生变化,进程B后运行,
//                它修改映射区域,然后退出,此时进程A能够观察到存储映射区的变化
//
// Created by FengQQ. 2020-10-02
//=============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>

int main(int argc,char *argv[])
{
	int fd;
	int ret;
	struct stat sb;
	char *mapped;
	
	fd = open(argv[1],O_RDWR);			//打开文件
	if(fd < 0)
	{
		printf("open failed...\r\n");
	}
	
	ret = fstat(fd,&sb);				//获取文件的属性
	if(ret < 0)
	{
		printf("fstat failed...\r\n");
	}
	//私有文件映射将无法修改文件
	mapped = (char *)mmap(NULL,sb.st_size,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0);
	if(mapped < 0)
	{
		printf("mmap failed...\r\n");
	}
	
	close(fd);							//映射完后, 关闭文件也可以操纵内存  
	
	mapped[20] = '9';					//修改一个字符
	
	return 0;
}

4.2.通过匿名映射实现父子进程通信

//=============================================================================
// File Name    : process_mmap_fork.c
// Author       : FengQQ
//
// Description  : 通过匿名映射实现父子进程通信
// Annotation   : 
//
// Created by FengQQ. 2020-10-02
//=============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>

#define BUF_SIZE 100

int main(int argc,char *argv[])
{
	char *p_map;
	
	//匿名映射,创建一块内存供父子进程通信 
	p_map = (char *)mmap(NULL,BUF_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
	
	if(fork() == 0)
	{
		sleep(1);
		printf("chail got a message: %s\r\n",p_map);
		sprintf(p_map,"%s","hi,dad,this is son.");
		munmap(p_map,BUF_SIZE);		//实际上,进程终止时,会自动解除映射
		exit(0);
	}
	
	sprintf(p_map,"%s","hi, this is father");
	sleep(2);
	printf("parent got a message: %s\r\n",p_map);

	return 0;
}

4.3.通过共享内存映射的方式修改文件

//=============================================================================
// File Name    : process_mmap.c
// Author       : FengQQ
//
// Description  : 通过共享内存映射的方式修改文件
// Annotation   : 运行: ./process_mmap data.txt
//
// Created by FengQQ. 2020-10-02
//=============================================================================
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/msg.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <error.h>

int main(int argc,char *argv[])
{
	
	int fd;
	int ret;
	char *mapped;
	struct stat sb;
	
	fd = open(argv[1],O_RDWR);						//打开文件
	if(fd < 0)
	{
		printf("open failed...\r\n");
	}
	
	ret = fstat(fd,&sb);							//获取文件的属性
	if(ret < 0)
	{
		printf("fstat failed...\r\n");
	}
	
	//将文件映射至进程的地址空间
	mapped = mmap(NULL,sb.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
	if(mapped < 0)
	{
		printf("mmap failed...\r\n");
	}
	
	mapped[19] = 'a';								//修改一个字符,同步到磁盘文件
	
	ret = msync((void *)mapped,sb.st_size,MS_SYNC);	//同步用的存储器用映射的文件
	if(ret < 0)
	{
		printf("msync failed...\r\n");	
		
		ret = munmap((void *)mapped,sb.st_size);	//释放存储映射区			
		if(ret < 0)
		{
			printf("munmap failed...\r\n");	
		}
	}
	
	return 0;
}

Linux进程间通信之共享内存(七)
链接: link.(https://blog.csdn.net/qq_39721016/article/details/119618664)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值