Linux系统编程61 高级IO - mmap()内存映射

存储映射IO:

mmap(): 将一块内存或者是某一个文件的存储内容 映射到当前进程空间里面来。结果就是 我们在当前进程中访问目标空间中的数据。

NAME
       mmap, munmap - map or unmap files or devices into memory

SYNOPSIS
       #include <sys/mman.h>

/* 映射,返回值为映射到的最终地址。
addr: 目标内存空间 放到当前进程空间的起始地址,若为空,则函数自己找可用的位置
length:需要映射目标空间的长度
port : 映射过来的内存属性,即可以对该内存做什么操作,即映射后的操作权限
       		     PROT_EXEC  Pages may be executed.
       PROT_READ  Pages may be read.
       PROT_WRITE Pages may be written.
       PROT_NONE  Pages may not be accessed.
flags :标记,特殊要求,位图
	必选:
	MAP_SHARED : 进程对进程对映射过来的内存修改,会同步到真实的内存空间。
	MAP_PRIVATE:进程对映射过来的内存修改,只是改动当前进程空间中目标内存空间,不会同步到真实的内存空间
	可选:
	如:MAP_ANONYMOUS 匿名映射,当前映射不依赖于任何文件(fd选项为-1),类似于 malloc()功能,空间会被初始化为0

fd : 文件描述符,如 需要映射一个文件过来,那么需要先将目标文件打开。
offset :偏移量
从 fd 文件的 offset偏移量开始映射,映射length长度的空间到当前进程空间的addr地址,空间权限设置为port ,特殊要求是flags 

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

/*解除映射
对 addr地址处 映射过来的空间(大小为length) 进行解除映射
如果 mmap()的时候 flags 有MAP_ANONYMOUS 匿名映射要求,则此处munmap() 类似于 free()
*/
int munmap(void *addr, size_t length);

RETURN VALUE

   On success, mmap() returns a pointer to the mapped area.  On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is set to indicate the cause of the error.

   On success, munmap() returns 0.  On failure, it returns -1, and errno is set to indicate the cause of the error (probably to EINVAL).

在这里插入图片描述

实验1 :查看一段内存空间中有多少 ‘a’。 用mmap()将目标空间映射过来,并做查找处理。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main(int argc,char *argv[])
{
	int fd;
	struct stat statres;
	char *str;
	int i,count=0;
	
	if(argc < 2)
	{
		fprintf(stderr,"Usage...\n");
		exit(1);
	}

	fd = open(argv[1],O_RDONLY);
	if(fd < 0)
	{
		perror("open()");
		exit(1);
	}
	

	if(fstat(fd,&statres) < 0)
	{
		perror("fstat()");
		exit(1);
	}
	str = mmap(NULL,statres.st_size,PROT_READ,MAP_SHARED,fd,0);
	if(str == MAP_FAILED)
	{
		perror("mmap()");
		exit(1);
	}

	close(fd);

	for(i = 0; i < statres.st_size; i++)
	{
		if(str[i] == 'a')
			count ++;
	}

	printf("%d\n",count);


	munmap(str,statres.st_size);
}

实验2:父子进程之间的通信,mmap()实现共享内存。

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

#define MEMSIZE 1024	

int main(int argc,char *argv[])
{
	char *ptr;
	pid_t pid;		

//不依赖于任何文件fd, 相当于 malloc()一段空间后映射过来,不依赖任何文件 所以fd==-1
	ptr = mmap(NULL,MEMSIZE,PROT_READ | PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
	if(ptr == MAP_FAILED)
	{
		perror("mmap()");
		exit(1);
	}


	pid = fork();//先mmap  后fork
	if(pid < 0)
	{
		perror("fork()");
		munmap(ptr,MEMSIZE);
		exit(1);
	}

	if(pid == 0) //Child write 
	{
		strcpy(ptr,"Hello!");
		munmap(ptr,MEMSIZE);
		exit(0);
	}
	else //Parent read
	{
		wait(NULL);
		puts(ptr);//puts()将字符串s和末尾的换行符写入标准输出。
		munmap(ptr,MEMSIZE);
		exit(0);
	}


}

猜你喜欢

转载自blog.csdn.net/LinuxArmbiggod/article/details/114692028