linux下的内存映射函数mmap详解及示例代码

合集下载

mmap函数详解

mmap函数详解

mmap函数详解mmap(Memory Mapped Files)函数是一种将文件映射到内存中的方法,在Unix和Linux系统中广泛使用。

该函数通过在进程地址空间中创建一个映射区域,将文件内容映射到这个区域,从而使得进程可以直接操作内存而无需进行文件读写操作。

mmap函数的语法如下所示:```cvoid *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);```其中,参数的含义如下:- addr:指定映射区域的起始地址,通常为NULL,表示由系统自动分配。

- length:指定映射区域的大小。

- prot:指定映射区域的访问权限,包括以下值之一:- PROT_READ:可读- PROT_WRITE:可写- PROT_EXEC:可执行- PROT_NONE:禁止访问- flags:指定映射区域的标志位,包括以下值之一或者多个:- MAP_PRIVATE:私有映射,对映射区域的修改不会影响到文件。

- MAP_SHARED:共享映射,对映射区域的修改会影响到文件。

- MAP_ANONYMOUS:匿名映射,不与任何文件相关联。

- MAP_FIXED:指定映射区域的起始地址不变。

- fd:指定要映射的文件描述符。

- offset:指定映射文件的起始偏移量。

当调用mmap函数时,系统会将文件内容读取到内核缓存中,然后将缓存中的内容映射到进程的虚拟地址空间中。

这样,进程就可以直接访问文件内容,而无需进行文件读写操作。

需要注意的是,当映射区域被释放时,操作系统会根据情况自动将缓存中的数据写回到对应的文件中。

综上所述,mmap函数是一种将文件映射到内存中的方法,通过直接访问内存来操作文件内容,可以提高程序的执行效率,并且可以方便地进行多进程之间的数据共享。

mmap函数参数讲解

mmap函数参数讲解

mmap函数参数讲解1.mmap-创建内存映射作⽤:将磁盘⽂件的数据映射到内存,⽤户通过内存就能修改磁盘⽂件函数原型:void *mmap{void *addr; //映射区⾸地址,传NULLsize_t length; //映射区的⼤⼩//会⾃动调为4k的整数倍//不能为0//⼀般⽂件多⼤,length就指定多⼤int prot; //映射区权限//PROT_READ 映射区⽐必须要有读权限//PROT_WRITE//PROT_READ | PROT_WRITEint flags; //标志位参数//MAP_SHARED 修改了内存数据会同步到磁盘//MAP_PRIVATE 修改了内存数据不会同步到磁盘int fd; //要映射的⽂件对应的fdoff_t offset; //映射⽂件的偏移量,从⽂件的哪⾥开始操作//映射的时候⽂件指针的偏移量//必须是4k的整数倍//⼀般设置为0}返回值:映射区的⾸地址-调⽤成功调⽤失败:MAP_FALED2.munmap-释放内存映射区函数原型:int munmap(void *addr,size_t length);addr-mmap的返回值length-mmap的第⼆个参数3.注意事项问:如果对mmap的返回值(ptr)做++操作(ptr++), munmap是否能够成功?答:不能问:如果open时O_RDONLY, mmap时prot参数指定PROT_READ | PROT_WRITE会怎样? 答mmap调⽤失败open⽂件指定权限应该⼤于等于mmap第三个参数prot指定的权限问:如果⽂件偏移量为1000会怎样?答:必须是4096的整数倍问:mmap什么情况下会调⽤失败?第⼆个参数length = 0第三个参数必须指定PROT_READfd对应的打开权限必须⼤于等于port权限偏移量:必须是4096的整数倍问:可以open的时候O_CREAT⼀个新⽂件来创建映射区吗?答:可以,需要做⽂件拓展lseektruncate(path,length)问:mmap后关闭⽂件描述符,对mmap映射有没有影响?答:没有问:对ptr越界操作会怎样?答:段错误4.mmap使⽤(1)基本代码#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <sys/mman.h>#include <fcntl.h>int main(int argc, const char* argv[]){//打开⼀个⽂件int fd=open("english.txt",O_RDWR);int len=lseek(fd,0,SEEK_END);//创建内存映射区void *ptr=mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); if(ptr==MAP_FAILED){perror("mmap error");exit(1);}printf("%s",(char*)ptr);//释放内存映射区munmap(ptr,len);close(fd);return 0;}运⾏结果:wangkai@wangkai-HP-242-G1-Notebook-PC:~/0110/6Day$ ./mmap sadaskdkasjsdasdasdasdasdsadasdsdasdas(2)使⽤mmap进⾏有⾎缘关系的进程间通信#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <string.h>#include <sys/mman.h>#include <sys/wait.h>#include <fcntl.h>/*利⽤mmap进⾏⽗⼦间通信,效率⽐⽂件I/O⾼,数据不是从磁盘上读,⽽是从内存上读写不阻塞,所以读之前⼀定要写好*/int main(int argc, const char* argv[]){//打开⼀个⽂件int fd=open("english.txt",O_RDWR);int len=lseek(fd,0,SEEK_END);//创建内存映射区void *ptr=mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); if(ptr==MAP_FAILED){perror("mmap error");exit(1);}close(fd);//创建⼦进程pid_t pid=fork();if(pid==-1){perror("fork error");exit(1);}if(pid>0){//写数据strcpy((char*)ptr,"我是你爸爸");//回收⼦进程wait(NULL);}else if(pid==0){//读数据printf("%s\n",(char*)ptr);}printf("%s",(char*)ptr);//释放内存映射区munmap(ptr,len);return 0;}(3)创建匿名映射区int len=4096;//创建匿名内存映射区,不指定⽂件void *ptr=mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON,-1,0);效果和(2)⼀样。

linux下的内存映射函数mmap详解及示例代码

linux下的内存映射函数mmap详解及示例代码

linux下的内存映射函数mmap详解及示例代码mmap()是一个在Linux 和其他UNIX-like 操作系统中使用的系统调用,用于创建一个到文件或其他对象的映射。

它将一个文件或其他对象映射进内存,文件或对象的内容可以像内存一样被访问。

以下是mmap()函数的基本语法:c#include<sys/mman.h>void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);参数说明:•start:映射的起始地址。

通常设置为NULL,表示让系统自动选择一个合适的地址。

•length:映射的长度,即要映射的字节数。

•prot:映射的保护方式。

可以是以下几种方式的组合:PROT_READ、PROT_WRITE、PROT_EXEC。

如果需要读写映射区域,应该同时设置PROT_READ和PROT_WRITE。

•flags:映射的标志。

可以是以下几种方式的组合:MAP_SHARED、MAP_PRIVATE、MAP_ANONYMOUS等。

•fd:要映射的文件描述符。

如果为-1,并且flags中包含MAP_ANONYMOUS,则不映射文件,而是创建一个匿名映射。

•offset:从文件中开始映射的偏移量。

返回值:•如果映射成功,返回一个指向映射区域的指针。

•如果映射失败,返回MAP_FAILED(通常为-1)。

下面是一个简单的使用mmap()的示例代码:c#include<stdio.h>#include<sys/mman.h>#include<fcntl.h>#include<unistd.h>#include<string.h>int main() {const char *filename = "test.txt";const char *content = "Hello, world!";size_t length = strlen(content) + 1; // 包括结尾的 '\0'int fd = open(filename, O_RDWR | O_CREAT, 0644); // 创建或打开文件,权限设置为 0644ftruncate(fd, length); // 设置文件大小为 length 字节write(fd, content, length); // 将 content 写入文件lseek(fd, 0, SEEK_SET); // 将文件指针重置到文件开头char *map = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); // 映射整个文件到内存中,可读写if (map == MAP_FAILED) { // 检查映射是否成功perror("mmap");return1;}printf("Content of the file: %s\n", map); // 输出映射区域的内容,即文件的内容munmap(map, length); // 解除映射,将内存归还给系统close(fd); // 关闭文件描述符return0;}这个示例代码创建或打开一个文件,将一个字符串写入文件,然后将整个文件映射到内存中,并输出内存中的内容。

Linux中关于MMAP and DMA的知识总结

Linux中关于MMAP and DMA的知识总结

3项技术:1,mmap系统调用可以实现将设备内存映射到用户进程的地址空间。

2,使用get_user_pages,可以把用户空间内存映射到内核中。

3,DMA的I/O操作,使得外设具有直接访问系统内存的能力。

-------------内存管理内核用来管理内存的数据结构---------地址内型Linux是一个虚拟内存系统,即用户程序使用的地址与硬件使用的物理地址是不等同的。

虚拟内存引入了一个间接层,使得许多操作成为可能:*有了虚拟内存,系统中运行的程序可以分配比物理内存更多的内存。

*虚拟地址还能让程序在进程的地址空间内使用更多的技巧,包括将程序的内存映射到设备内存上。

地址内型列表*用户虚拟地址每个进程都有自己的虚拟地址空间。

*物理地址处理器访问系统内存时使用的地址。

*总线地址在外围总线和内存之间使用。

MMU可以实现总线和主内存之间的重新映射。

当设置DMA操作时,编写MMU相关的代码是一个必需的步骤。

*内核逻辑地址内核逻辑地址组成了内核的常规地址空间,该地址映射了部分(或全部)内存,并经常被视为物理地址。

在大多数体系架构中,逻辑地址与其相关联的物理地址的不同,仅仅在于它们之间存在一个固定的偏移量。

kmalloc返回的内存就是内核逻辑地址。

*内核虚拟地址内核虚拟地址与逻辑地址相同之处在于,都将内核空间的地址映射到物理地址上。

不同之处在于,内核虚拟地址与物理地址的映射不是线性的和一对一的。

vmalloc返回一个虚拟地址,kmap函数也返回一个虚拟地址。

------------------物理地址和页物理地址被分为离散的单元,称之为页。

系统内部许多对内存的操作都是基于单个页的。

大多数系统都使用每页4096个字节,PAGE_SIZE <asm/page.h>给出指定体系架构下的页大小。

观察内存地址,无论是虚拟的还是物理的,它们都被分为页号和一个页内的偏移量。

如果每页4096个字节,那么最后的12位就是偏移量,剩余的高位则指定页号。

linux mmap 原理

linux mmap 原理

linux mmap 原理摘要:I.引言- 简述Linux mmap 的作用和重要性II.Linux mmap 原理- 解释mmap 系统调用的功能和参数- 分析mmap 系统调用的工作原理- 介绍mmap与文件I/O的关系III.mmap 的应用场景- 列举mmap 在实际应用中的例子IV.mmap 的优缺点- 分析mmap 的优点- 分析mmap 的缺点V.结论- 总结mmap 的重要性及其在Linux 中的地位正文:I.引言Linux mmap 是Linux 系统中一个非常重要的系统调用,它可以将文件或设备的内容映射到进程的虚拟内存空间,从而实现对文件或设备的高效访问。

通过使用mmap,进程可以像操作内存一样操作文件或设备,这大大提高了程序的执行效率。

本文将详细介绍Linux mmap 的原理、应用场景及其优缺点。

II.Linux mmap 原理Linux mmap 系统调用函数原型为:void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)。

参数说明如下:- addr:指向映射内存的起始地址,通常设为NULL,让系统自动选定地址。

- len:需要映射的字节数。

- prot:映射内存的保护位,包括PROT_READ(可读)、PROT_WRITE (可写)和PROT_EXEC(可执行)。

- flags:映射标志位,包括MAP_SHARED(共享映射)和MAP_PRIVATE(私有映射)。

- fd:文件描述符,对应要映射的文件或设备。

- offset:文件或设备中的偏移量,映射的起始地址由文件描述符和偏移量共同确定。

当进程调用mmap 系统调用时,内核会根据参数在文件或设备中找到对应的内存区域,将其映射到进程的虚拟内存空间。

如果文件或设备的内容发生变化,进程可以通过操作虚拟内存来更新文件或设备的内容。

mmap参数说明

mmap参数说明

mmap参数说明mmap参数说明介绍mmap是一种在内存和文件之间创建映射关系的机制,在Linux系统中被广泛使用。

它可以实现将一个文件或者其他设备映射到进程的地址空间,使得进程可以通过访问内存的方式来读写文件。

本文将介绍mmap的一些常用参数及其说明。

参数列表以下是一些常用的mmap参数及其说明:1.addr:指定映射区域的起始地址,一般为0,表示由系统自动分配。

2.length:指定映射区域的长度,单位是字节。

3.prot:指定映射区域的访问权限,可选值包括PROT_READ、PROT_WRITE、PROT_EXEC等。

4.flags:指定映射区域的标志,可选值包括MAP_SHARED、MAP_PRIVATE等。

MAP_SHARED表示映射的文件可以被多个进程共享,MAP_PRIVATE表示映射的文件只能被当前进程使用。

5.fd:指定要映射的文件描述符。

6.offset:指定要映射文件的偏移量。

使用示例下面是一个使用mmap的示例代码,演示了如何使用mmap将一个文件映射到内存中进行读写操作:#include <>#include <>#include <>#include <sys/>int main() {int fd;char *data;struct stat sb;// 打开文件fd = open("", O_RDWR);if (fd == -1) {perror("open");exit(1);}// 获取文件大小if (fstat(fd, &sb) == -1) {perror("fstat");exit(1);}// 映射文件到内存data = mmap(NULL, _size, PROT_READ | PROT_WRITE, MAP _SHARED, fd, 0);if (data == MAP_FAILED) {perror("mmap");exit(1);}// 访问文件数据printf("File data: %s\n", data);// 修改文件数据data[0] = 'H';data[1] = 'e';data[2] = 'l';data[3] = 'l';data[4] = 'o';// 解除内存映射if (munmap(data, _size) == -1) {perror("munmap");exit(1);}// 关闭文件if (close(fd) == -1) {perror("close");exit(1);}return 0;}以上示例代码展示了如何将一个文件映射到内存中并修改文件数据。

Linux内存映射文件mmap

Linux内存映射文件mmap
此外还有其他几个flags不很常用, 具体查看linux C函数说明.
fd: 由open返回的文件描述符, 代表要映射的文件.
offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.
下面说一下内存映射的步骤:
用open系统调用打开文件, 并返回描述符fd.
用mmap建立内存映射, 并返回映射首地址指针start.
对映射(文件)进行各种操作, 显示(printf), 修改(sprintf).
用munmap(void *start, size_t lenght)关闭内存映射.
用close系统调用关闭文件fd.
Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明:
头文件:
<unistd.h>
<sys/mman.h>
原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);
PROT_WRITE: 映射区可被写入.
PROT_NONE: 映射区不能AP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共享.
MAP_PRIVATE: 对映射区域的写入操作会产生一个映射的复制(copy-on-write), 对此区域所做的修改不会写回原文件.
返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).
参数:
addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.

linux drivers中的mmap实现

linux drivers中的mmap实现

linux drivers中的mmap实现drivers中file_operations的mmap操作的作用是:将设备驱动内核空间的内存映射到用户空间里,可以通过用户空间中的mmap系统调用代替系统调用write和read。

目的是提高读写效率。

系统调用mmap:void* mmap (caddr_t addr, size_t len, int prot, int flags, off_t offset)其中addr一般为NULL,目的是使内核自动分配可用的虚拟空间地址,并通过返回值返回,并与MAP_FAILED比较;prot一般为PROT_WRITE | PROT_READ; flags为MAP_SHARED或MAP_PRIV ATE之一;offset表示从设备文件都开始多大偏移处映射,一般为0。

文件操作mmap :int (*mmap) (struct file* filp, struct vm_area_struct* vma)定义struct vm_operaTIons_struct xxx_vm_ops = {.open = xxx_vm_open,.close = xxx_vm_close,.nopage = xxx_vm_nopage,};编写mmap文件操作函数的方式有两种:一.使用remap_pfn_range一次性申请,不需要定义nopage函数1.在mmap中调用remap_pfn_range;2.在mmap中对vma->vm_ops进行附值;3.在mmap结尾处主动调用vm_ops中的open;二.定义nopage函数,在发生缺页时由内核申请内存中的物理页,由driver在nopage中将page与vma挂钩1.mmap中除了对vma->vm_ops进行附值和主动调用vm_ops中的open外;2.将设备内存首先按PAGE_SIZE对齐,最终只将页对齐的设备内存映射到用户空间中。

mmap_munmap

mmap_munmap
18 perror("FB_DEVICE_OPEN");
19 exit (1);
20 }
21 fbp = (unsigned short *)mmap(NULL,
22 SCREEN_SIZE * sizeof(unsigned short),
MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。
MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。
fd:有效的文件描述词。如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1。
12 int main(int argc, char * argv[])
13 {
14 int fbfd, i;
15 unsigned color=0;
16 unsigned short *fbp;
17 if((fbfd = open (FB_DEVICE, O_RDWR))< 0) {
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <string.h>
6 #include <sys/mman.h>
7 #include <sys/types.h>
27 if(fbp ==NULL || fbp == (unsigned short *)(-1)) {
28 ERROR("cannot mmap device");

mmap参数说明

mmap参数说明

mmap参数说明1. 简介mmap(memory map)是一种用于在用户空间和内核空间之间共享内存的机制。

通过使用mmap函数,可以将一个文件映射到内存中,从而实现对文件的随机访问。

mmap函数在Linux系统中非常常用,并且在许多应用程序中发挥着重要作用。

2. mmap函数原型void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offse t);•addr:指定映射区域的首地址,通常设置为NULL,表示由系统自动分配。

•length:映射区域的长度。

•prot:指定映射区域的保护模式,可以是以下几个值的按位或:–PROT_READ:可读–PROT_WRITE:可写–PROT_EXEC:可执行–PROT_NONE:不可访问•flags:指定映射区域的类型和属性,可以是以下几个值的按位或:–MAP_SHARED:共享映射–MAP_PRIVATE:私有映射–MAP_FIXED:强制指定映射区域的起始地址•fd:文件描述符,表示要映射到内存中的文件。

如果不需要将文件内容映射到内存中,则设置为-1。

•offset:偏移量,表示从文件起始位置开始映射的偏移量。

3. mmap函数返回值mmap函数的返回值是映射区域的起始地址,如果出错则返回MAP_FAILED。

可以通过检查返回值是否等于MAP_FAILED来判断mmap函数是否执行成功。

4. 使用mmap函数实现文件映射下面是一个使用mmap函数实现文件映射的示例:#include <stdio.h>#include <stdlib.h>#include <sys/mman.h>#include <fcntl.h>#include <unistd.h>int main() {int fd;char *addr;struct stat sb;fd = open("file.txt", O_RDONLY);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}if (fstat(fd, &sb) == -1) {perror("fstat");exit(EXIT_FAILURE);}addr = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);if (addr == MAP_FAILED) {perror("mmap");exit(EXIT_FAILURE);}printf("%s", addr);if (munmap(addr, sb.st_size) == -1) {perror("munmap");exit(EXIT_FAILURE);}close(fd);return 0;}在上述示例中,首先使用open函数打开一个名为file.txt的文件,并获取其文件描述符。

Linux之V4L2基础编程_内存映射

Linux之V4L2基础编程_内存映射
fprintf(stderr, "Cannot open '%s': %d, %s\n", cam_name, errno, strerror(errno));
return fd; }
四、 获取设备信息
/************************************************************************************************************* ioctl (fd, VIDIOC_QUERYCAP, &cap),这个 ioctl 函数用来确认这个设备是否和内核驱动相兼容,如果不兼容则返回
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == FAILURE)
{
printf("Error in VIDIOC_S_FMT\n");
return FAILURE;
} else {
printf("width=%d\n",fmt.fmt.pix.width);
printf("height=%d\n",fmt.fmt.pix.height);
}
if (!S_ISCHR(st.st_mode)){ fprintf(stderr, "%s is no device\n",cam_name); exit(EXIT_FAILURE);
}
fd = open(cam_name, O_RDWR/*required */ | O_NONBLOCK, 0); if(-1 == fd)
三、 打开设备并进行错误检查
static int open_cam(void) {

mmap的返回值

mmap的返回值

mmap的返回值Mmap的返回值介绍mmap()是一种内存映射文件的机制,它可以使得文件在内存中呈现出一个连续的地址空间。

这个地址空间可以被读取、写入和执行,就像普通的内存一样。

mmap()函数的返回值是指向映射区域的指针。

本文将详细介绍mmap()函数返回值以及相关知识点。

mmap()函数在了解mmap()函数返回值之前,我们先来看一下mmap()函数的定义:```void * mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);```其中各参数含义如下:- addr:映射区域的首地址。

如果为NULL,则由系统自动分配。

- length:映射区域的长度。

- prot:映射区域的保护方式。

可选项包括PROT_READ、PROT_WRITE、PROT_EXEC和PROT_NONE。

- flags:标志位,用于控制映射区域是否可共享、是否支持修改等等。

可选项包括MAP_SHARED、MAP_PRIVATE、MAP_FIXED等等。

- fd:要映射到内存中的文件描述符。

- offset:要映射到内存中的文件偏移量。

mmap()函数返回值mmap()函数成功时返回指向映射区域首地址的指针,失败时返回MAP_FAILED。

因为MAP_FAILED的值通常为(void*)-1,所以我们可以用如下方式来判断mmap()函数是否成功:```void *p = mmap(...);if (p == MAP_FAILED) {perror("mmap");exit(EXIT_FAILURE);```如果mmap()函数调用失败,会设置errno变量。

如果需要打印错误信息,可以使用perror()函数。

映射区域的地址在调用mmap()函数时,我们可以指定映射区域的首地址(addr参数)。

如果addr参数为NULL,则由系统自动分配一个合适的地址作为映射区域的首地址。

linux 内存映射 mmap用法

linux 内存映射 mmap用法

linux 内存映射mmap用法一mmap系统调用1.内存映射所谓的内存映射就是把物理内存映射到进程的地址空间之内,这些应用程序就可以直接使用输入输出的地址空间,从而提高读写的效率。

Linux 提供了mmap()函数,用来映射物理内存。

在驱动程序中,应用程序以设备文件为对象,调用mmap()函数,内核进行内存映射的准备工作,生成vm_area_struct结构体,然后调用设备驱动程序中定义的mmap 函数。

2.mmap系统调用mmap将一个文件或者其它对象映射进内存。

文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。

munmap执行相反的操作,删除特定地址区域的对象映射。

当使用mmap映=映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写等操作,不必再调用read,write等系统调用.但需注意,直接对该段内存写时不会写入超过当前文件大小的内容采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。

对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。

实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。

而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。

共享内存中的内容往往是在解除映射时才写回文件的。

因此,采用共享内存的通信方式效率是非常高的。

基于文件的映射,在mmap和munmap执行过程的任何时刻,被映射文件的st_atime可能被更新。

如果st_atime字段在前述的情况下没有得到更新,首次对映射区的第一个页索引时会更新该字段的值。

用PROT_WRITE 和MAP_SHARED标志建立起来的文件映射,其st_ctime 和st_mtime在对映射区写入之后,但在msync()通过MS_SYNC 和MS_ASYNC两个标志调用之前会被更新。

linux下的内存映射函数mmap详解及示例代码

linux下的内存映射函数mmap详解及示例代码

linux下的内存映射函数mmap详解及示例代码引言概述:在Linux操作系统中,内存映射函数mmap是一种重要的内存管理工具。

它可以将文件或设备映射到进程的地址空间,使得进程可以直接访问这些映射区域的数据。

本文将详细介绍mmap函数的使用方法及示例代码,并从五个方面进行阐述。

正文内容:1. mmap函数的基本介绍1.1 mmap函数的定义和原理1.2 mmap函数的参数和返回值1.3 mmap函数的使用场景和优势2. mmap函数的使用方法2.1 打开文件或设备2.2 调用mmap函数进行内存映射2.3 对映射区域进行读写操作2.4 解除内存映射关系2.5 关闭文件或设备3. mmap函数的常见应用场景3.1 文件的内存映射3.2 共享内存的实现3.3 零拷贝技术的应用3.4 设备的内存映射3.5 动态库的加载和执行4. mmap函数的示例代码4.1 文件的内存映射示例4.2 共享内存的示例4.3 零拷贝技术的示例4.4 设备的内存映射示例4.5 动态库的加载和执行示例5. mmap函数的注意事项和优化技巧5.1 内存对齐的重要性5.2 内存映射的大小和文件大小的关系5.3 内存映射的权限设置5.4 内存映射的性能优化5.5 内存映射的错误处理总结:通过本文的介绍,我们了解了Linux下内存映射函数mmap的详细内容。

我们讨论了mmap函数的基本介绍和使用方法,并给出了常见的应用场景和示例代码。

此外,我们还提到了使用mmap函数时需要注意的事项和优化技巧。

mmap函数在Linux系统中具有重要的作用,熟练掌握它的使用方法对于开发高效、稳定的应用程序非常重要。

mmap()函数解析

mmap()函数解析

mmap()函数解析mmap可以把磁盘⽂件的⼀部分直接映射到内存,这样⽂件中的位置直接就有对应的内存地址,对⽂件的读写可以直接⽤指针来做⽽不需要read/write函数。

#include <sys/mman.h>void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);int munmap(void *addr, size_t len);该函数各参数的作⽤图⽰如下:图 28.4. mmap函数如果addr参数为NULL,内核会⾃⼰在进程地址空间中选择合适的地址建⽴映射。

如果addr不是NULL,则给内核⼀个提⽰,应该从什么地址开始映射,内核会选择addr之上的某个合适的地址开始映射。

建⽴映射后,真正的映射⾸地址通过返回值可以得到。

len参数是需要映射的那⼀部分⽂件的长度。

off参数是从⽂件的什么位置开始映射,必须是页⼤⼩的整数倍(在32位体系统结构上通常是4K)。

filedes是代表该⽂件的描述符。

prot参数有四种取值:PROT_EXEC表⽰映射的这⼀段可执⾏,例如映射共享库PROT_READ表⽰映射的这⼀段可读PROT_WRITE表⽰映射的这⼀段可写PROT_NONE表⽰映射的这⼀段不可访问flag参数有很多种取值,这⾥只讲两种,其它取值可查看mmap(2)MAP_SHARED多个进程对同⼀个⽂件的映射是共享的,⼀个进程对映射的内存做了修改,另⼀个进程也会看到这种变化。

MAP_PRIVATE多个进程对同⼀个⽂件的映射不是共享的,⼀个进程对映射的内存做了修改,另⼀个进程并不会看到这种变化,也不会真的写到⽂件中去。

如果mmap成功则返回映射⾸地址,如果出错则返回常数MAP_FAILED。

当进程终⽌时,该进程的映射内存会⾃动解除,也可以调⽤munmap解除映射。

munmap成功返回0,出错返回-1。

mmap详解

mmap详解

一.前言mmap的具体实现以前在学习内核时学习过,但是对于其中的很多函数是一知半解的,有些只能根据其函数名来猜测其具体的功能,在本文中,一起来重新深入理解其具体的实现。

二.mmap的用户层应用void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize);具体参数含义start :指向欲映射的内存起始地址,通常设为 NULL,代表让系统自动选定地址,映射成功后返回该地址。

length:代表将文件中多大的部分映射到内存。

prot :映射区域的保护方式。

可以为以下几种方式的组合:PROT_EXEC 映射区域可被执行PROT_READ 映射区域可被读取PROT_WRITE 映射区域可被写入PROT_NONE 映射区域不能存取flags :影响映射区域的各种特性。

在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。

MAP_FIXED 如果参数start所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。

通常不鼓励用此旗标。

MAP_SHARED 对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。

MAP_PRIVATE 对映射区域的写入操作会产生一个映射文件的复制,即私人的“写入时复制”(copy on write)对此区域作的任何修改都不会写回原来的文件内容。

MAP_ANONYMOUS建立匿名映射。

此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。

MAP_DENYWRITE只允许对映射区域的写入操作,其他对文件直接写入的操作将会被拒绝。

MAP_LOCKED 将映射区域锁定住,这表示该区域不会被置换(swap)。

fd :要映射到内存中的文件描述符。

如果使用匿名内存映射时,即flags 中设置了MAP_ANONYMOUS,fd设为-1。

有些系统不支持匿名内存映射,则可以使用fopen打开/dev/zero文件,然后对该文件进行映射,可以同样达到匿名内存映射的效果。

Linux内存映射函数mmap()函数详解

Linux内存映射函数mmap()函数详解

Linux内存映射函数mmap()函数详解mmap将一个文件或者其它对象映射进内存。

文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。

mmap在用户空间映射调用系统中作用很大。

头文件 <sys/mman.h>函数原型void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);int munmap(void* start,size_t length);mmap()[1] 必须以PAGE_SIZE为单位进行映射,而内存也只能以页为单位进行映射,若要映射非PAGE_SIZE整数倍的地址范围,要先进行内存对齐,强行以PAGE_SIZE的倍数大小进行映射。

用法:下面说一下内存映射的步骤:用open系统调用打开文件, 并返回描述符fd.用mmap建立内存映射,并返回映射首地址指针start.对映射(文件)进行各种操作, 显示(printf), 修改(sprintf).用munmap(void *start, size_t lenght)关闭内存映射.用close系统调用关闭文件fd.UNIX网络编程第二卷进程间通信对mmap函数进行了说明。

该函数主要用途有三个:1、将一个普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写,以获得较高的性能;2、将特殊文件进行匿名内存映射,可以为关联进程提供共享内存空间;3、为无关联的进程提供共享内存空间,一般也是将一个普通文件映射到内存中。

函数:void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize); 参数start:指向欲映射的内存起始地址,通常设为 NULL,代表让系统自动选定地址,映射成功后返回该地址。

linux 共享内存 mmap函数

linux 共享内存 mmap函数

linux 共享内存 mmap函数
在Linux中,我们可以使用 mmap 函数来创建共享内存区域,从而实现进程间的数据共享。

mmap 函数将一段物理内存映射到进程的虚拟地址空间中,从而使得不同进程可以访问同一段物理内存。

具体来说,我们可以通过以下步骤来创建和使用共享内存:
1. 使用 shmget 函数获取一个共享内存标识符,如果该标识符不存在,则创建一个新的共享内存区域;
2. 使用 mmap 函数将共享内存区域映射到进程的虚拟地址空间中,并返回一个指向该区域的指针;
3. 使用该指针就可以在不同进程之间访问共享内存了;
4. 使用 munmap 函数将共享内存区域从进程的虚拟地址空间中解除映射;
5. 最后使用 shmctl 函数删除共享内存区域。

需要注意的是,共享内存虽然可以提高进程间通信的效率,但同时也带来了数据竞争的风险,需要在代码中采取相应的同步措施来避免问题的发生。

- 1 -。

mmap 参数

mmap 参数

mmap 参数
mmap(memory map)是一种在内存和文件之间建立映射关系的机制。

在Linux系统中,mmap函数通过将文件映射到进程的虚拟内存空间,让进程能够对文件进行读写操作,实现了高效的文件I/O操作。

mmap函数的参数包括:
1. start:指向欲映射的内存起始地址,通常置为0,表示让系统自动选择地址。

2. length:映射的内存区域的长度,单位是字节。

3. prot:映射区域的保护方式,包括PROT_EXEC、
PROT_READ、PROT_WRITE和PROT_NONE等。

4. flags:映射区域的标志,包括MAP_SHARED和
MAP_PRIVATE等。

5. fd:打开的文件描述符。

6. offset:映射区域在文件中的偏移量。

7. 返回值:成功返回映射区的首地址,失败返回
MAP_FAILED。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

自:/flying5/blog 不错的博客,大家可以去看看Linux的mmap文件内存映射机制mmap: memory map在讲述文件映射的概念时, 不可避免的要牵涉到虚存(SVR 4的VM). 实际上, 文件映射是虚存的中心概念, 文件映射一方面给用户提供了一组措施, 好似用户将文件映射到自己地址空间的某个部分, 使用简单的内存访问指令读写文件;另一方面, 它也可以用于内核的基本组织模式, 在这种模式种, 内核将整个地址空间视为诸如文件之类的一组不同对象的映射. 中的传统文件访问方式是, 首先用open系统调用打开文件, 然后使用read, write以及lseek等调用进行顺序或者随即的I/O. 这种方式是非常低效的, 每一次I/O操作都需要一次系统调用. 另外, 如果若干个进程访问同一个文件, 每个进程都要在自己的地址空间维护一个副本, 浪费了内存空间. 而如果能够通过一定的机制将页面映射到进程的地址空间中, 也就是说首先通过简单的产生某些内存管理数据结构完成映射的创建. 当进程访问页面时产生一个缺页中断, 内核将页面读入内存并且更新页表指向该页面. 而且这种方式非常方便于同一副本的共享.VM是面向对象的方法设计的, 这里的对象是指内存对象: 内存对象是一个软件抽象的概念, 它描述内存区与后备存储之间的映射. 系统可以使用多种类型的后备存储, 比如交换空间, 本地或者远程文件以及帧缓存等等. VM 系统对它们统一处理, 采用同一操作集操作, 比如读取页面或者回写页面等. 每种不同的后备存储都可以用不同的方法实现这些操作. 这样, 系统定义了一套统一的接口, 每种后备存储给出自己的实现方法. 这样, 进程的地址空间就被视为一组映射到不同数据对象上的的映射组成. 所有的有效地址就是那些映射到数据对象上的地址. 这些对象为映射它的页面提供了持久性的后备存储. 映射使得用户可以直接寻址这些对象.值得提出的是, VM体系结构独立于Unix系统, 所有的Unix系统语义, 如正文, 数据及堆栈区都可以建构在基本VM系统之上. 同时, VM体系结构也是独立于存储管理的, 存储管理是由操作系统实施的, 如: 究竟采取什么样的对换和请求调页算法, 究竟是采取分段还是分页机制进行存储管理, 究竟是如何将虚拟地址转换成为物理地址等等(Linux中是一种叫Three Level Page Table的机制), 这些都与内存对象的概念无关.下面介绍Linux中VM的实现.一个进程应该包括一个mm_struct(memory manage struct),该结构是进程虚拟地址空间的抽象描述, 里面包括了进程虚拟空间的一些管理信息: start_code, end_code, start_data, end_data, start_brk, end_brk等等信息. 另外, 也有一个指向进程虚存区表(vm_area_struct: virtual memory area)的指针, 该链是按照虚拟地址的增长顺序排列的. 在Linux进程的地址空间被分作许多区(vma), 每个区(vma)都对应虚拟地址空间上一段连续的区域, vma是可以被共享和保护的独立实体, 这里的vma就是前面提到的内存对象. 下面是vm_area_struct的结构, 其中, 前半部分是公共的, 与类型无关的一些数据成员, 如: 指向mm_struct的指针, 地址范围等等, 后半部分则是与类型相关的成员, 其中最重要的是一个指向vm_operation_struct向量表的指针vm_ops, vm_pos向量表是一组虚函数, 定义了与vma类型无关的接口. 每一个特定的子类, 即每种vma类型都必须在向量表中实现这些操作. 这里包括了: open, close, unmap, protect, sync, nopage, wppage, swapout这些操作.struct vm_area_struct {/*公共的, 与vma类型无关的*/struct mm_struct * vm_mm;unsigned long vm_start;unsigned long vm_end;struct vm_area_struct *vm_next;pgprot_t vm_page_prot;unsigned long vm_flags;short vm_avl_height;struct vm_area_struct * vm_avl_left;struct vm_area_struct * vm_avl_right;struct vm_area_struct *vm_next_share;struct vm_area_struct **vm_pprev_share;/* 与类型相关的*/struct vm_operations_struct * vm_ops;unsigned long vm_pgoff;struct file * vm_file;unsigned long vm_raend;void * vm_private_data;};vm_ops: open, close, no_page, swapin, swapout……介绍完VM的基本概念后, 我们可以讲述mmap和munmap系统调用了. mmap调用实际上就是一个内存对象vma的创建过程, mmap的调用格式是:void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);其中start是映射地址, length是映射长度, 如果flags的MAP_FIXED不被置位, 则该参数通常被忽略, 而查找进程地址空间中第一个长度符合的空闲区域;Fd是映射文件的文件句柄, offset是映射文件中的偏移地址;prot是映射保护权限, 可以是PROT_EXEC, PROT_READ, PROT_W RITE, PROT_NONE, flags则是指映射类型, 可以是MAP_FIXED, MAP_PRIVATE, MAP_SHARED, 该参数必须被指定为MAP_PRIVATE和MAP_SHARED 其中之一, MAP_PRIVATE是创建一个写时拷贝映射(copy-on-write), 也就是说如果有多个进程同时映射到一个文件上, 映射建立时只是共享同样的存储页面, 但是某进程企图修改页面内容, 则复制一个副本给该进程私用, 它的任何修改对其它进程都不可见.而MAP_SHARED则无论修改与否都使用同一副本, 任何进程对页面的修改对其它进程都是可见的.mmap系统调用的实现过程是:1.先通过文件系统定位要映射的文件;2.权限检查, 映射的权限不会超过文件打开的方式, 也就是说如果文件是以只读方式打开, 那么则不允许建立一个可写映射;3.创建一个vma对象, 并对之进行初始化;4.调用映射文件的mmap函数, 其主要工作是给vm_ops向量表赋值;5.把该vma链入该进程的vma链表中, 如果可以和前后的vma合并则合并;6.如果是要求VM_LOCKED(映射区不被换出)方式映射, 则发出缺页请求, 把映射页面读入内存中.munmap(void * start, size_t length):该调用可以看作是mmap的一个逆过程. 它将进程中从start开始length长度的一段区域的映射关闭, 如果该区域不是恰好对应一个vma, 则有可能会分割几个或几个vma.msync(void * start, size_t length, int flags):把映射区域的修改回写到后备存储中. 因为munmap时并不保证页面回写, 如果不调用msync, 那么有可能在munmap后丢失对映射区的修改. 其中flags可以是MS_SYNC, MS_ASYNC, MS_INVALIDATE, MS_SYNC要求回写完成后才返回, MS_ASYNC发出回写请求后立即返回, MS_INVALIDATE使用回写的内容更新该文件的其它映射. 该系统调用是通过调用映射文件的sync函数来完成工作的.brk(void * end_data_segement):将进程的数据段扩展到end_data_segement指定的地址, 该系统调用和mmap的实现方式十分相似, 同样是产生一个vma, 然后指定其属性. 不过在此之前需要做一些合法性检查, 比如该地址是否大于mm->end_code,end_data_segement和mm->brk之间是否还存在其它vma等等. 通过brk产生的vma映射的文件为空, 这和匿名映射产生的vma相似, 关于匿名映射不做进一步介绍. 库函数malloc就是通过brk实现的.===============================================Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明:头文件:<unistd.h><sys/mman.h>原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).参数:addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.length: 将文件的多大长度映射到内存.prot: 映射区的保护方式, 可以是:PROT_EXEC: 映射区可被执行.PROT_READ: 映射区可被读取.PROT_WRITE: 映射区可被写入.PROT_NONE: 映射区不能存取.flags: 映射区的特性, 可以是:MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共享.MAP_PRIVATE: 对映射区域的写入操作会产生一个映射的复制(copy-on-write), 对此区域所做的修改不会写回原文件.此外还有其他几个flags不很常用, 具体查看linux C函数说明.fd: 由open返回的文件描述符, 代表要映射的文件.offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.下面说一下内存映射的步骤:用open系统调用打开文件, 并返回描述符fd.用mmap建立内存映射, 并返回映射首地址指针start.对映射(文件)进行各种操作, 显示(printf), 修改(sprintf).用munmap(void *start, size_t lenght)关闭内存映射.用close系统调用关闭文件fd.注意事项:在修改映射的文件时, 只能在原长度上修改, 不能增加文件长度, 因为内存是已经分配好的.Linux-mmap函数介绍(转)mmap函数是unix/linux下的系统调用,来看《Unix Netword programming》卷二12.2节对mmap的介绍:The mmap function maps either a file or a Posix shared memory object into the address space of a process.We use this function for three purposes:1. with a regular file to provide memory-mapped I/O2. with special files to provide anonymous memory mappings3. with shm_open to provide Posix shared memory between unrelated processesmmap系统调用并不是完全为了用于共享内存而设计的。

相关文档
最新文档