linux 内存映射 mmap用法

合集下载

linux包之procps之pmap命令

linux包之procps之pmap命令

linux包之procps之pmap命令名称:pmap - report memory map of a process(查看进程的内存映像信息)⽤法pmap [ -x | -d ] [ -q ] pids...pmap -V选项含义-x extended Show the extended format. 显⽰扩展格式-d device Show the device format. 显⽰设备格式-q quiet Do not display some header/footer lines. 不显⽰头尾⾏-V show version Displays version of program. 显⽰版本扩展格式和设备格式域:Address: start address of map 映像起始地址Kbytes: size of map in kilobytes 映像⼤⼩RSS: resident set size in kilobytes 驻留集⼤⼩Dirty: dirty pages (both shared and private) in kilobytes 脏页⼤⼩Mode: permissions on map 映像权限: r=read, w=write, x=execute, s=shared, p=private (copy on write)Mapping: file backing the map , or '[ anon ]' for allocated memory, or '[ stack ]' for the program stack. 映像⽀持⽂件,[anon]为已分配内存[stack]为程序堆栈Offset: offset into the file ⽂件偏移Device: device name (major:minor) 设备名pmap -d 1pmap -d 1 -q 不显⽰头尾[root@C44 ~]# while true; do pmap -d 3066 | tail -1; sleep 2; done 循环显⽰进程3066的设备格式的最后1⾏,间隔2秒,最后⼀⾏的值mapped 表⽰该进程映射的虚拟地址空间⼤⼩,也就是该进程预先分配的虚拟内存⼤⼩,即ps出的vszwriteable/private 表⽰进程所占⽤的私有地址空间⼤⼩,也就是该进程实际使⽤的内存⼤⼩shared 表⽰进程和其他进程共享的内存⼤⼩[root@250-shiyan bin]# pmap -x 1464414644: sshd: root@pts/0Address Kbytes RSS Dirty Mode Mapping00007f979d216000 964944944 rw--- [ anon ]00007f979d3a0000 128044 rw-s- zero (deleted)00007f979d4e0000 16160 r-x-- pam_limits.so00007f979d4e4000 204400 ----- pam_limits.so00007f979d6e3000 444 r---- pam_limits.so00007f979d6e4000 444 rw--- pam_limits.so00007f979d6e5000 880 r-x-- pam_keyinit.so[root@250-shiyan bin]# pmap -d 1464414644: sshd: root@pts/0Address Kbytes Mode Offset Device Mapping00007f979d216000 964 rw--- 0000000000000000000:00000 [ anon ]00007f979d3a0000 1280 rw-s- 0000000000000000000:00004 zero (deleted)00007f979d4e0000 16 r-x-- 0000000000000000 0fd:00000 pam_limits.so00007f979d4e4000 2044 ----- 0000000000004000 0fd:00000 pam_limits.so[root@221-comecs ~]# watch -d -n 1 'ss -n|grep 10001'15:19:16 23 ~:#uptime15:28:15 up 38 days, 3:57, 2 users, load average: 0.00, 0.00, 0.00snice与skill是⼀对,pgrep与pkill是⼀对pgrep, pkill - look up or signal processes based on name and other attributespgrep根据⽤户名,命令名或者其它属性过滤出pid,⾮常⽅便,pkill发送相应的信号[root@109-com1 bin]# pgrep F26195root 26195 1 4 Jul23 pts/2 01:00:28 /usr/local/ps/bin/FLTService15:31:39 25 ~:#ldd /usr/bin/uptimelinux-vdso.so.1 => (0x00007fff291ff000)libproc-3.2.8.so => /lib64/libproc-3.2.8.so (0x00007f2a52250000) libc.so.6 => /lib64/libc.so.6 (0x00007f2a51ebc000)/lib64/ld-linux-x86-64.so.2 (0x00007f2a5247a000)15:31:52 26 ~:#ldd /usr/bin/wlinux-vdso.so.1 => (0x00007fffd8326000)libproc-3.2.8.so => /lib64/libproc-3.2.8.so (0x00007f4f54789000) libc.so.6 => /lib64/libc.so.6 (0x00007f4f543f5000)/lib64/ld-linux-x86-64.so.2 (0x00007f4f549b3000)15:32:15 27 ~:#ldd /usr/bin/vmstatlinux-vdso.so.1 => (0x00007fff029ff000)libproc-3.2.8.so => /lib64/libproc-3.2.8.so (0x00007fbf227d6000) libc.so.6 => /lib64/libc.so.6 (0x00007fbf22442000)/lib64/ld-linux-x86-64.so.2 (0x00007fbf22a00000)procps相关⼯具都调⽤同⼀个库[oracle@localhost ~]$ rpm -ql procps/bin/ps/lib64/libproc-3.2.8.so/lib64/libproc.so/sbin/sysctl/usr/bin/free/usr/bin/pgrep/usr/bin/pkill/usr/bin/pmap/usr/bin/pwdx/usr/bin/skill/usr/bin/slabtop/usr/bin/snice/usr/bin/tload/usr/bin/top/usr/bin/uptime/usr/bin/vmstat/usr/bin/w/usr/bin/watch。

mmap和普通文件读写的区别和比较mmap的注意点

mmap和普通文件读写的区别和比较mmap的注意点

mmap和普通⽂件读写的区别和⽐较mmap的注意点参考对linux⽂件系统不了解的朋友,请参阅我之前写的博⽂《》,我们⾸先简单的回顾⼀下常规⽂件系统操作(调⽤read/fread等类函数)中,函数的调⽤过程:1、进程发起读⽂件请求。

2、内核通过查找进程⽂件符表,定位到内核已打开⽂件集上的⽂件信息,从⽽找到此⽂件的inode。

3、inode在address_space上查找要请求的⽂件页是否已经缓存在页缓存中。

如果存在,则直接返回这⽚⽂件页的内容。

4、如果不存在,则通过inode定位到⽂件磁盘地址,将数据从磁盘复制到页缓存。

之后再次发起读页⾯过程,进⽽将页缓存中的数据发给⽤户进程。

总结来说,常规⽂件操作为了提⾼读写效率和保护磁盘,使⽤了页缓存机制。

这样造成读⽂件时需要先将⽂件页从磁盘拷贝到页缓存中,由于页缓存处在内核空间,不能被⽤户进程直接寻址,所以还需要将页缓存中数据页再次拷贝到内存对应的⽤户空间中。

这样,通过了两次数据拷贝过程,才能完成进程对⽂件内容的获取任务。

写操作也是⼀样,待写⼊的buffer在内核空间不能直接访问,必须要先拷贝⾄内核空间对应的主存,再写回磁盘中(延迟写回),也是需要两次数据拷贝。

⽽使⽤mmap操作⽂件中,创建新的虚拟内存区域和建⽴⽂件磁盘地址和虚拟内存区域映射这两步,没有任何⽂件拷贝操作。

⽽之后访问数据时发现内存中并⽆数据⽽发起的缺页异常过程,可以通过已经建⽴好的映射关系,只使⽤⼀次数据拷贝,就从磁盘中将数据传⼊内存的⽤户空间中,供进程使⽤。

总⽽⾔之,常规⽂件操作需要从磁盘到页缓存再到⽤户主存的两次数据拷贝。

⽽mmap操控⽂件,只需要从磁盘到⽤户主存的⼀次数据拷贝过程。

说⽩了,mmap的关键点是实现了⽤户空间和内核空间的数据直接交互⽽省去了空间不同数据不通的繁琐过程。

因此mmap效率更⾼。

mmap优点总结由上⽂讨论可知,mmap优点共有⼀下⼏点:1、对⽂件的读取操作跨过了页缓存,减少了数据的拷贝次数,⽤内存读写取代I/O读写,提⾼了⽂件读取效率。

大页内存--mmap

大页内存--mmap

⼤页内存--mmap1.为什么要使⽤⼤页内存 了解操作系统内存管理的⼈⼀般都知道操作系统对内存采⽤多级页表和分页进⾏管理,操作系统每个页默认⼤⼩为4KB。

如果进程使⽤的内存过⼤,⽐如1GB,这样会在页表中占⽤ 1GB / 4KB = 262144个页表项,⽽系统TLB可以容纳的页表项远⼩于这个数量。

当多个内存密集型应⽤访问内存时,会造成过多的TLB未命中,因此在特定情况下会需要减少未命中次数,⼀个可⾏的办法就是增⼤每个页的尺⼨。

操作系统默认⽀持的⼤页是2MB,当使⽤1GB内存时,在页表中将占⽤ 1GB / 2MB = 512个页表项,可以⼤⼤提升TLB命中率,进⽽提升应⽤性能。

2.怎样使⽤⼤页内存2.1 先预留⼀定量的⼤页内存#先查看系统有多少已经预留的⼤页内存# cat /proc/meminfo |grep -i huge#预留192个⼤页# sysctl vm.nr_hugepages=192#查看是否预留成功# cat /proc/meminfo |grep -i huge2.2 通过系统调⽤来从预留的⼤页内存中申请⼤页#include <sys/mman.h>#include <stdio.h>#include <memory.h>int main(int argc, char *argv[]) {char *m;size_t s = (8UL * 1024 * 1024);m = mmap(NULL, s, PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS | 0x40000 /*MAP_HUGETLB*/, -1, 0);if (m == MAP_FAILED) {perror("map mem");m = NULL;return 1;}memset(m, 0, s);printf("map_hugetlb ok, press ENTER to quit!\n");getchar();munmap(m, s);return 0;}3.最后的话⼤页内存的好处不仅是减少TLB未命中次数,⽽且⼤页内存分配的是物理内存,不会被操作系统的内存管理换出到磁盘上,因此不会出现缺页中断,也就不会引⼊访问磁盘的时延,另外,⼤页内存在物理上是连续的,对于⼤内存访问也有⼀定的加速效果。

linux的memmap参数

linux的memmap参数

linux的memmap参数在Linux操作系统中,memmap参数是一个非常重要的系统调用参数,它决定了内存映射的容量和限制。

本文将详细介绍memmap参数的含义、作用、设置方法以及使用技巧,帮助读者更好地理解和应用Linux操作系统。

一、memmap参数概述memmap参数是Linux内核参数之一,用于控制内存映射的大小和范围。

它决定了系统可以映射多少物理内存到虚拟内存,以及哪些物理内存可以被映射。

通过设置memmap参数,可以控制系统的内存使用效率,优化系统的性能和稳定性。

二、memmap参数的作用1.内存管理:memmap参数控制了内存映射的范围和容量,从而影响了系统的内存管理策略。

合理的memmap参数设置可以提高系统的内存利用率,减少内存碎片和浪费。

2.性能优化:通过合理设置memmap参数,可以减少系统对物理内存的占用,提高系统的响应速度和运行效率。

同时,合理的内存映射还可以减少数据传输的开销,提高系统的整体性能。

3.系统稳定性:合理的memmap参数设置可以避免系统因内存不足而出现崩溃或死机等问题,从而提高系统的稳定性和可靠性。

三、memmap参数的设置方法Linux系统中,可以通过修改内核配置文件或使用系统调用方式来设置memmap参数。

常用的方法包括:1.修改内核配置文件:在Linux系统中,内核配置文件通常位于/boot/config-<kernel-version>目录下。

可以通过编辑该文件来修改memmap参数的值,并使用makemenuconfig或makexconfig等工具重新编译内核。

2.使用系统调用:在Linux系统中,可以使用mmap()系统调用来映射内存。

通过指定memmap参数的值,可以控制可映射的物理内存大小。

四、使用memmap参数的技巧在使用memmap参数时,需要注意以下几点:1.合理设置memmap参数的值:要根据系统的实际需求和硬件配置来设置合适的memmap参数值,避免过度占用物理内存导致系统性能下降或崩溃。

归纳整理Linux下C语言常用的库函数----文件操作

归纳整理Linux下C语言常用的库函数----文件操作

归纳整理Linux下C语⾔常⽤的库函数----⽂件操作在没有IDE的时候,记住⼀些常⽤的库函数的函数名、参数、基本⽤法及注意事项是很有必要的。

参照Linux_C_HS.chm的⽬录,我⼤致将常⽤的函数分为⼀下⼏类:1. 内存及字符串控制及操作2. 字符串转换3. 字符测试4. ⽂件操作5. 时间⽇期6. 常⽤数学函数7. ⽂件内容操作8. ⽂件权限控制9. 进程操作10. 线程操作11. Socket操作12. 信号处理13. 数据结构及算法这次主要总结的是上⾯⿊⾊部分,关于⽂件操作的函数。

系统调⽤归类** 函数名⽤法备注**1. int open(const char *pathname, int flags); open and possibly create a file or device flags 必须包含O_RDONLY, O_WRONLY, or O_RDWR中的任何⼀个**2. int open(const char *pathname, int flags, mode_t mode); UP mode只是在flags中包含O_CREAT时才有效**3. int fsync(int fd); synchronize a file's in-core state with storage device 写完数据close前必须先同步,以防意外**4. off_t lseek(int fd, off_t offset, int whence); 定位⽂件位置第三个参数可以为SEEK_SET SEEK_CUR SEEK_END**5. ssize_t read(int fildes, void *buf, size_t nbyte); UP ⽂件位置会随读取的字节数移动**6. ssize_t write(int fildes, const void *buf, size_t nbyte); UP UP**7. int close(int fd); UP UP**8. void *mmap(void *addr, size_t length, int prot, int flags, 内存映射先⽤fstat得到⽂件⼤⼩,然后使⽤该函数将⽂件内容映射到内存中,然后就可以int fd, off_t offset); 直接调⽤字符串函数操作。

Linux_Memory_Address_Mapping

Linux_Memory_Address_Mapping

Linux内存地址映射 目 录1概述 (3)2IA-32体系结构内存地址映射 (4)2.1CPU相关寄存器 (4)2.1.1系统寄存器 (5)2.1.2内存管理寄存器 (5)2.2保护模式的内存管理 (7)2.332位时页面机制地址映射 (9)2.3.1逻辑地址到线性地址的映射 (9)2.3.2线性地址到物理地址的映射 (11)2.4PAE页面机制地址映射过程 (12)2.4.1PDPTE寄存器 (12)2.4.2逻辑地址到线性地址的映射 (13)2.4.3线性地址到物理地址的映射 (13)3Linux内核的地址映射过程 (15)3.1段式映射过程 (15)3.2页式映射过程 (17)4Linux地址映射实验 (19)4.1gdtr和cr3寄存器值的获取 (20)4.2读取物理内存上的数据 (21)4.3地址映射过程实验 (21)4.3.1段式映射过程 (23)4.3.2页式映射过程 (24)4.4PAE机制下地址映射过程实验 (26)4.4.1段式映射过程 (26)4.4.2页式映射过程 (27)5常见问题及解答 (28)1 概述在分析Linux内存地址映射前,先来看一段简单的C程序代码在32位和64位系统上运行结果:#include <stdio.h>int main(){unsigned long tmp;tmp = 0x12345678;printf("tmp variable address:0x%08lX\n", &tmp);return 0;}[root@RHEL6 C]# ./addrtmp variable address:0xBFF42DEC[root@RHEL6 C]#[root@RHEL6-x64-1 C]# ./addrtmp variable address:0x7FFF138E0888上面的程序功能非常简单,就是打印出临时变量tmp的地址。

munmap函数用法

munmap函数用法
munmap函数用于释放由mmap函数映射的内存区域,将这些内存区域从进程的地址空间中删除。

munmap函数的原型如下:
```
#include <unistd.h>
int munmap(void *addr, size_t length);
```
其中,addr为mmap函数返回的映射地址,length为映射区域的长度。

使用munmap函数需要注意以下几点:
1. 释放的内存区域必须是通过mmap函数映射得到的,否则会导致未定义的行为。

2. 释放的内存区域必须是整个映射区域,而不能是其中的一部分。

3. 释放后的内存区域不再可用,任何对该区域的访问都将导致未定义的行为。

4. 释放的内存区域必须是页对齐的,否则会导致段错误。

munmap函数的返回值为0表示成功,-1表示失败,失败时可以通过errno变量获取错误信息。

常见的错误包括EINVAL(参数无效)、ENOMEM(内存不足)和EBADF(无效的文件描述符)等。

使用munmap函数释放内存区域是一种常见的内存管理技术。

在使用mmap函数映射内存时,通常需要在使用完内存后及时释放,以
避免内存泄漏和资源浪费。

文件映射 原理

文件映射原理
文件映射是一种计算机存储技术,其原理是将文件系统中的文件与内存中的地址空间进行对应。

通过文件映射,可以使文件在内存中的访问方式与访问普通内存相同,从而简化对文件的读写操作。

具体来说,文件映射通过以下步骤实现:
1. 打开文件:首先,需要使用文件系统提供的接口打开待映射的文件。

这个步骤通常包括指定文件名、路径等信息来定位文件。

2. 创建映射:接下来,需要调用操作系统提供的函数,将文件映射到内存中。

在Windows系统中,可使用CreateFileMapping函数来创建文件映射对象;而在Linux系统中,可以使用mmap函数完成映射。

3. 映射文件到内存:一旦创建了文件映射对象,就可以将其映射到进程的虚拟地址空间中。

文件映射可以将整个文件或者指定的部分映射到内存中,形成映射区域。

4. 内存操作:一旦映射成功,可以将内存中的映射区域当作普通的内存进行读写操作。

对映射区域的读写实际上是对文件的读写操作,映射区域的更新会直接影响到文件的内容。

5. 解除映射:当不再需要使用文件映射时,可以调用相应的函数解除映射。

在Windows系统中,使用CloseHandle函数来关
闭文件映射对象;在Linux系统中,可以使用munmap函数来解除映射。

文件映射的实现原理是利用操作系统的虚拟内存机制。

通过将文件映射到内存中的虚拟地址空间,使得对文件的读写操作可以通过内存地址来完成,而不需要使用文件系统相关的函数。

文件映射的好处是可以提高对文件的读写效率,因为内存访问要比文件访问速度更快。

此外,多个进程可以共享同一个文件的映射,实现数据的共享和通信。

linux c map 用法

linux c map 用法在Linux C中,Map是一个非常常用的数据结构。

它提供了一种键值对的映射关系,即可以根据特定的键获取对应的值。

C语言中没有内置的Map类型,但可以使用多种方法实现类似的功能。

下面是关于Linux C中Map的用法的相关参考内容。

1. 使用结构体数组一种常见的实现Map的方法是使用结构体数组。

结构体中有两个成员:键和值。

通过比较键的值,可以找到对应的值。

```ctypedef struct {int key;int value;} KeyValue;KeyValue map[CAPACITY]; // 定义Map的大小void insert(int key, int value) {// 在Map中插入键值对// 可以使用循环遍历结构体数组,查找键是否已经存在// 如果存在,更新对应的值,如果不存在,将新的键值对插入到结构体数组的最后}int get(int key) {// 根据给定的键获取对应的值// 可以使用循环遍历结构体数组,找到匹配的键值对,返回对应的值}void remove(int key) {// 根据给定的键删除键值对// 可以使用循环遍历结构体数组,找到匹配的键值对,将其删除并将后面的元素向前移动}```2. 使用哈希表另一种常见的实现Map的方法是使用哈希表。

哈希表通过哈希函数将给定的键转换成数组的索引,然后将键值对存储在数组中。

```ctypedef struct {int key;int value;} KeyValue;#define CAPACITY 100 // 定义哈希表的大小KeyValue map[CAPACITY];int hash(int key) {// 哈希函数,将给定的键转换成数组的索引}void insert(int key, int value) {// 在哈希表中插入键值对// 根据哈希函数将键转换成数组的索引,如果该索引已经被占用,可以使用开放地址法解决碰撞问题// 如果哈希表已满,可以考虑扩容}int get(int key) {// 根据给定的键获取对应的值// 根据哈希函数将键转换成数组的索引,如果存在,返回对应的值}void remove(int key) {// 根据给定的键删除键值对// 根据哈希函数将键转换成数组的索引,如果存在,将其删除}```3. 使用开源库除了自己实现Map,还可以使用开源库来实现Map的功能。

Linux读写memory操作,devmem直接访问物理内存地址【转】

Linux读写memory操作,devmem直接访问物理内存地址【转】1 说明由于开发需要,需要通过memory传输数据,所以使⽤devmem ⽅式读写数据,操作linux 内存数据。

devmem的⽅式是提供给驱动开发⼈员,在应⽤层能够侦测内存地址中的数据变化,以此来检测驱动中对内存或者相关配置的正确性验证。

2 开发环境软件环境: ubuntu 虚拟机、arm-xilinx 交叉编译⼯具链硬件环境: ZYNQ70103 内存地址说明基本上的内存物理地址都可以访问,但是如果需要ZYNQ的PS 和PL 都能读写数据,需要查看芯⽚的datasheet,确定哪个地址可以互相读写数据。

通过《ug585-Zynq-7000-TRM.pdf》的 29章表格“Table 29‐1: Initial OCM/DDR Address Map” 可以得到地址分配。

表3-1 ZYNQ7010 芯⽚地址分配从表格3-1得知,DDR的物理地址对应为 0x0010_0000 - 3FFF_FFFF4 devmem ⼯具⼯具的原理也⽐较简单,就是应⽤程序通过mmap函数实现对/dev/mem驱动中mmap⽅法的使⽤,映射了设备的内存到⽤户空间,实现对这些物理地址的读写操作。

代码如下:/*** @addtogroup module_devmem* @{*//*** @file* @brief 内存管理⼯具,仿照标准linux devmem ⼯具进⾏改良,可以⾃由读写linux内存数据。

* @details 驱动接⼝。

* @version 1.1.0* @author sky.houfei* @date 2019-8-6*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <errno.h>#include <signal.h>#include <fcntl.h>#include <ctype.h>#include <termios.h>#include <sys/types.h>#include <sys/mman.h>#include <stdbool.h>//*****************************************************************************#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)#define MAP_SIZE 4096UL //映射的内存区⼤⼩(⼀般为⼀个叶框⼤⼩)#define MAP_MASK (MAP_SIZE - 1) //MAP_MASK = 0XFFF//*****************************************************************************/*** @brief 直接写⼊到内存实际的物理地址。

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

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两个标志调用之前会被更新。

用法:#include <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()返回被映射区的指针,munmap()返回0。

失败时,mmap()返回MAP_FAILED[其值为(void *)-1],munmap返回-1。

errno被设为以下的某个值EACCES:访问出错EAGAIN:文件已被锁定,或者太多的内存已被锁定EBADF:fd不是有效的文件描述词EINVAL:一个或者多个参数无效ENFILE:已达到系统对打开文件的限制ENODEV:指定文件所在的文件系统不支持内存映射ENOMEM:内存不足,或者进程已超出最大内存映射数量EPERM:权能不足,操作不允ETXTBSY:已写的方式打开文件,同时指定MAP_DENYWRITE标志SIGSEGV:试着向只读区写入SIGBUS:试着访问不属于进程的内存区参数:start:映射区的开始地址。

length:映射区的长度。

prot:期望的内存保护标志,不能与文件的打开模式冲突。

是以下的某个值,可以通过or运算合理地组合在一起PROT_EXEC //页内容可以被执行PROT_READ //页内容可以被读取PROT_WRITE //页可以被写入PROT_NONE //页不可访问flags:指定映射对象的类型,映射选项和映射页是否可以共享。

它的值可以是一个或者多个以下位的组合体MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。

如果指定的起始地址不可用,操作将会失败。

并且起始地址必须落在页的边界上。

MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。

对共享区的写入,相当于输出到文件。

直到msync()或者munmap()被调用,文件实际上不会被更新。

MAP_PRIVATE //建立一个写入时拷贝的私有映射。

内存区域的写入不会影响到原文件。

这个标志和以上标志是互斥的,只能使用其中一个。

MAP_DENYWRITE //这个标志被忽略。

MAP_EXECUTABLE //同上MAP_NORESERVE //不要为这个映射保留交换空间。

当交换空间被保留,对映射区修改的可能会得到保证。

当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。

MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。

MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。

MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。

MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。

MAP_FILE //兼容标志,被忽略。

MAP_32BIT //将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。

当前这个标志只在x86-64平台上得到支持。

MAP_POPULATE //为文件映射通过预读的方式准备好页表。

随后对映射区的访问不会被页违例阻塞。

MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。

不执行预读,只为已存在于内存中的页面建立页表入口。

fd:有效的文件描述词。

如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1。

offset:被映射对象内容的起点。

3.munmap系统调用#include <sys/mman.h>int munmap( void * addr, size_t len )该调用在进程地址空间中解除一个映射关系,addr是调用mmap()时返回的地址,len是映射区的大小。

当映射关系解除后,对原来映射地址的访问将导致段错误发生。

4.msync系统调用#include <sys/mman.h>int msync ( void * addr , size_t len, int flags)一般说来,进程在映射空间的对共享内容的改变并不直接写回到磁盘文件中,往往在调用munmap()后才执行该操作。

可以通过调用msync()实现磁盘上文件内容与共享内存区的内容一致。

二系统调用mmap()用于共享内存的两种方式(1)使用普通文件提供的内存映射:适用于任何进程之间;此时,需要打开或创建一个文件,然后再调用mmap();典型调用代码如下:fd=open(name, flag, mode);if(fd<0)...ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0);通过mmap()实现共享内存的通信方式有许多特点和要注意的地方(2)使用特殊文件提供匿名内存映射:适用于具有亲缘关系的进程之间;由于父子进程特殊的亲缘关系,在父进程中先调用mmap(),然后调用fork()。

那么在调用fork()之后,子进程继承父进程匿名映射后的地址空间,同样也继承mmap()返回的地址,这样,父子进程就可以通过映射区域进行通信了。

注意,这里不是一般的继承关系。

一般来说,子进程单独维护从父进程继承下来的一些变量。

而mmap()返回的地址,却由父子进程共同维护。

对于具有亲缘关系的进程实现共享内存最好的方式应该是采用匿名内存映射的方式。

此时,不必指定具体的文件,只要设置相应的标志即可. 三mmap进行内存映射的原理mmap系统调用的最终目的是将,设备或文件映射到用户进程的虚拟地址空间,实现用户进程对文件的直接读写,这个任务可以分为以下三步:1.在用户虚拟地址空间中寻找空闲的满足要求的一段连续的虚拟地址空间,为映射做准备(由内核mmap系统调用完成)每个进程拥有3G字节的用户虚存空间。

但是,这并不意味着用户进程在这3G的范围内可以任意使用,因为虚存空间最终得映射到某个物理存储空间(内存或磁盘空间),才真正可以使用。

那么,内核怎样管理每个进程3G的虚存空间呢?概括地说,用户进程经过编译、链接后形成的映象文件有一个代码段和数据段(包括data 段和bss段),其中代码段在下,数据段在上。

数据段中包括了所有静态分配的数据空间,即全局变量和所有申明为static的局部变量,这些空间是进程所必需的基本要求,这些空间是在建立一个进程的运行映像时就分配好的。

除此之外,堆栈使用的空间也属于基本要求,所以也是在建立进程时就分配好的在内核中,这样每个区域用一个结构struct vm_area_struct 来表示.它描述的是一段连续的、具有相同访问属性的虚存空间,该虚存空间的大小为物理内存页面的整数倍。

可以使用cat /proc/<pid>/maps来查看一个进程的内存使用情况,pid是进程号.其中显示的每一行对应进程的一个vm_area_struct结构.struct vm_area_struct {struct mm_struct * vm_mm; /* The address space we belong to. */unsigned long vm_start; /* Our start address within vm_mm. */unsigned long vm_end; /* The first byte after our end addresswithin vm_mm. *//* linked list of VM areas per task, sorted by address */struct vm_area_struct *vm_next, *vm_prev;pgprot_t vm_page_prot; /* Access permissions of this VMA. */ unsigned long vm_flags; /* Flags, see mm.h. */struct rb_node vm_rb;/** For areas with an address space and backing store,* linkage into the address_space->i_mmap prio tree, or* linkage to the list of like vmas hanging off its node, or* linkage of vma in the address_space->i_mmap_nonlinear list.*/union {struct {struct list_head list;void *parent; /* aligns with prio_tree_node parent */struct vm_area_struct *head;} vm_set;struct raw_prio_tree_node prio_tree_node;} shared;/** A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma* list, after a COW of one of the file pages. A MAP_SHARED vma* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack* or brk vma (with NULL file) can only be in an anon_vma list.*/struct list_head anon_vma_chain; /* Serialized by mmap_sem &* page_table_lock */struct anon_vma *anon_vma; /* Serialized by page_table_lock *//* Function pointers to deal with this struct. */const struct vm_operations_struct *vm_ops;/* Information about our backing store: */unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZEunits, *not* PAGE_CACHE_SIZE */ struct file * vm_file; /* File we map to (can be NULL). */void * vm_private_data; /* was vm_pte (shared mem) */unsigned long vm_truncate_count;/* truncate_count or restart_addr */#ifndef CONFIG_MMUstruct vm_region *vm_region; /* NOMMU mapping region */#endif#ifdef CONFIG_NUMAstruct mempolicy *vm_policy; /* NUMA policy for the VMA */#endif};通常,进程所使用到的虚存空间不连续,且各部分虚存空间的访问属性也可能不同。

相关文档
最新文档