天天看点

Linux虚拟内存及内存映射

1.没有虚拟内存的CPU基本不能运行多任务操作系统,不能支持多进程。

2.实现虚拟内存技术主要有2种:段式内存管理和页式内存管理,目前页式内存管理占主流。

3.页式内存管理将内存划分成大小相同的页面,每个进程地址空间可以由多个页面构成,实现进程空间的隔离。

4。为什么要使用内存映射:传统读写文件的方式过程是open->read/write/lseek->close每一次调用都要执行系统调用,效率极低;如果多个进程要访问同一个文件,那么每一个进程都需要在自己的内存地址空间维护一个副本,这是一种浪费。而使用mmap将文件当做内存(数组等)操作就不存在这样的问题。

Linux内存映射:Linux内核将整个内存地址空间看做是一系列不同的"文件"映射,不过在这个叫内核对象。Linux加载内核到内存的过程就是内存映射的过程,甚至加载可执行文件的过程也是内存映射。

5.32位地址虚拟内存:32位的虚拟内存地址最大能管理4G的物理地址。32位的虚拟地址分成3部分:页面目录|页面表|页内偏移(10|10|12),页面目录能管理1024个页面表,页面表能管理1024个页面(每1024个页面就分成一个页面表,页面表地址放在页面目录数组中;1024个页面的地址放在页面表数组中)

6.虚拟地址到物理地址的转换可以有很多应用:进程与进程之间可以虚拟地址相同但物理地址不同,从而达到空间上的真正隔离;利用页面交换技术可以将一个文件映射到内存中,使得mmap这样的系统调用得以实现;将相同的虚拟地址转换成相同的物理地址这样可以实现数据共享如线程;将硬件设备的控制存储区反映到虚拟内存中,可以通过内存直接控制设备;...

7.内存映射的缺点

内存映射可能存在的对存储物理空间的浪费:每次在不同或相同进程对同一个文件调用mmap时内存映射技术将总是分配一个新的页偏移为0的页面给进程,这样导致多次调用mmap写入的数据是不连续的。每次调用mmap写入的数据相对4096取余数越小,那么浪费的空间可能越多。

8.mmap系统调用

void* mmap(void* addr,size_t len,int prot,int flag,int filedes,off_t off);

int munmap(void* addr,size_t len); //释放映射

 #include <stdio.h>  

 #include <unistd.h>  

 #include <stdlib.h>  

 #include <string.h>  

 #include <fcntl.h>  

 #include <linux/fb.h>  

 #include <sys/mman.h>  

 #include <sys/ioctl.h>   

 #define PAGE_SIZE 4096  

 int main(int argc , char *argv[])

 {

     int fd;

     int i;

     unsigned char *p_map;

     //打开设备  

     fd = open("liujin.txt",O_RDWR);

     if(fd < 0)

     {

         printf("open fail\n");

         exit(1);

     }

     //内存映射  

     p_map = (unsigned char *)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);

     if(p_map == MAP_FAILED)

         printf("mmap fail\n");

         goto here;

     snprintf(p_map+5,10,"bye!");

     //打印映射后的内存中的前10个字节内容  

     for(i=0;i<10;i++)  

         printf("%c\n",p_map[i]);  

 here:  

     munmap(p_map, PAGE_SIZE);  

     return 0;  

 } 

查看文件中的数据:od -tx1 -tc liujin.txt 

本文转自 a_liujin 51CTO博客,原文链接:http://blog.51cto.com/a1liujin/1880652,如需转载请自行联系原作者

继续阅读