溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

LINUX中的mmap是什么

發(fā)布時間:2021-08-18 20:14:27 來源:億速云 閱讀:180 作者:chen 欄目:建站服務(wù)器

本篇內(nèi)容主要講解“LINUX中的mmap是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“LINUX中的mmap是什么”吧!



LINUX 中的mmap淺析

一、mmap基本原理和分類
在LINUX中我們可以使用mmap用來在進(jìn)程虛擬地址空間中分配創(chuàng)建一片虛擬內(nèi)存地址映射
其可以是
1、文件映射
   使用文件內(nèi)容初始化內(nèi)存
2、匿名映射
   初始化全為0的內(nèi)存空間(calloc也可以)
下面配圖來自UNIX系統(tǒng)編程手冊
LINUX中的mmap是什么

而對于是否共享又分為
1、私有映射(MAP_PRIVATE)
   多進(jìn)程間數(shù)據(jù)共享,修改不反應(yīng)到磁盤實際文件,
   私有寫時復(fù)制實現(xiàn)
2、共享映射(MAP_SHARED)
   多進(jìn)程間數(shù)據(jù)共享,修改反應(yīng)到磁盤實際文件中。
那么總結(jié)起來有4種組合
1、私有文件映射
   多個進(jìn)程使用同樣的物理內(nèi)存頁進(jìn)行初始化,但是各個進(jìn)程
   對內(nèi)存文件的修改不會共享,也不會反應(yīng)到物理文件中,比如
   我們LINUX .so動態(tài)庫文件就采用這種方式映射到各個進(jìn)程虛擬
   地址空間中
2、私有匿名映射
   mmap會創(chuàng)建一個新的映射,各個進(jìn)程不共享,這種使用主要用于
   分配內(nèi)存(malloc分配大內(nèi)存會調(diào)用mmap)。
3、共享文件映射
   多個進(jìn)程通過虛擬內(nèi)存技術(shù)共享同樣的物理內(nèi)存空間,對內(nèi)存文件
   的修改會反應(yīng)到實際物理文件中,他也是進(jìn)程間通信(IPC)的一種機(jī)制
4、共享匿名映射
   這種機(jī)制在進(jìn)行fork的時候不會采用寫時復(fù)制,父子進(jìn)程完全共享
   同樣的物理內(nèi)存頁,這也就實現(xiàn)了父子進(jìn)程通信(IPC).
下面也是UNIX系統(tǒng)編程手冊截圖
LINUX中的mmap是什么
在/proc/PID/maps下我們可以找到一個當(dāng)前進(jìn)程使用mmap創(chuàng)建的映射比如:
379a000000-379a016000 r-xp 00000000 08:03 12320771                       /lib64/libgcc_s-4.4.7-20120601.so.1
379a016000-379a215000 ---p 00016000 08:03 12320771                       /lib64/libgcc_s-4.4.7-20120601.so.1
379a215000-379a216000 rw-p 00015000 08:03 12320771                       /lib64/libgcc_s-4.4.7-20120601.so.1
379a400000-379a4e8000 r-xp 00000000 08:03 9700201                        /usr/lib64/libstdc++.so.6.0.13
379a4e8000-379a6e8000 ---p 000e8000 08:03 9700201                        /usr/lib64/libstdc++.so.6.0.13
379a6e8000-379a6ef000 r--p 000e8000 08:03 9700201                        /usr/lib64/libstdc++.so.6.0.13
379a6ef000-379a6f1000 rw-p 000ef000 08:03 9700201                        /usr/lib64/libstdc++.so.6.0.13
對于解釋可以參考UNIX系統(tǒng)編程手冊如下描述
LINUX中的mmap是什么
   
二、mmap函數(shù)原型

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
參數(shù)有點多
addr:映射放到哪里(虛擬地址),一般傳NULL,讓內(nèi)核自己決定
length:映射的大小(直接),最小是系統(tǒng)頁的整數(shù)倍(4K)
port:位圖掩碼 
     PROT_NONE   不能訪問
     PROT_READ   可讀取
     PROT_WRITE  可修改
     PROT_EXEC   可執(zhí)行
     非法訪問或報SIGSEGV段錯誤信號
flags:位圖掩碼 
      MAP_ANONYMOUS:創(chuàng)建一個匿名映射
      MAP_PRIVATE:私有映射
      MAP_SHARED:共享映射(注意并不能保證一定實際寫入物理磁盤(MSYNC))
      MAP_FIXED:addr必須是頁對齊地址
      其他標(biāo)示不做解釋
fd:映射文件的文件描述符
offset:從文件的哪個位置開始映射,必須是系統(tǒng)頁的整數(shù)倍(4K)

返回值:
成功返回映射的虛擬內(nèi)存地址的起始地址,失敗返回MAP_FAILED

三、建立匿名映射
1、指針MAP_ANONYMOUS,并且fd指定為0
2、打開/dev/zero文件將文件描述符傳遞給mmap()
匿名映射會分配初始化全為0的虛擬內(nèi)存空間

四、其他函數(shù)
int msync(void *addr, size_t length, int flags);
用于將kener buffer的數(shù)據(jù)同步到磁盤
int munmap(void *addr, size_t length);
用于解除映射

五、程序?qū)嵗?br/>下面我們通過mmap做私有匿名映射來完成一個小的線程間同步問題程序,用這片
內(nèi)存區(qū)域來做線程間通信

點擊(此處)折疊或打開

  1. #include<iostream>

  2. #include<sys/mman.h>

  3. #include<pthread.h>

  4. #include<string.h>

  5. #define uint unsigned int

  6. #define MMSIZE (uint)(1<<23)

  7. #define MSIZE (uint)(1<<20)

  8. #define MPRT (uint)(1<<16)

  9. using namespace std;




  10. class tc

  11. {

  12.         private:

  13.                 uint a;

  14.         public:

  15.                 tc():a(1)

  16.         {

  17.                 ;

  18.         }

  19.                 ~tc()

  20.                 {

  21.                         ;

  22.                 }

  23.                 void add()

  24.                 {

  25.                         a=a+1;

  26.                 }

  27.                 void set()

  28.                 {

  29.                         a=1;

  30.                 }

  31.                 void prt(int i)

  32.                 {

  33.                         if(!(i%(MPRT)))

  34.                         {

  35.                                 cout<<":"<<a;

  36.                         }

  37.                 }


  38. };


  39. struct tt

  40. {

  41.         tc* p1;

  42.         pthread_mutex_t* p2;

  43. };


  44. void* test(void* arg)

  45. {

  46.         int i = 0;

  47.         tt* s = NULL;

  48.         s = (tt*)arg;

  49.         int maxloop = 50;

  50.         while(maxloop--)

  51.         {

  52.                 i = MSIZE;

  53.                 pthread_mutex_lock(s->p2);//MUTEX保護(hù)臨界區(qū)

  54.                 cout<<"Thread:"<<pthread_self()<<" work now!!!\n";

  55.                 for(;i--;)

  56.                 {

  57.                         (s->p1+i)->prt(i);

  58.                         (s->p1+i)->add();

  59.                 }

  60.                 cout<<"\n";

  61.                 pthread_mutex_unlock(s->p2);//解鎖

  62.         }

  63. }




  64. int main(void)

  65. {

  66.         pthread_t tid[3];

  67.         pthread_mutex_t pmut;

  68.         tt s1;

  69.         tc* p = (tc*)mmap(NULL,MMSIZE,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);//MMAP分配一個匿名私有虛擬內(nèi)存用于線程間通信

  70.         pthread_mutex_init(&pmut,NULL);

  71.         s1.p1 = p;

  72.         s1.p2 = &pmut;


  73.         int i = MSIZE+1;


  74.         for(;i--;)

  75.         {

  76.                 (p+i)->set();//初始化所有的a=1

  77.         }



  78.         for(i=0;i<3;i++)

  79.         {

  80.                 pthread_create(tid+i,NULL,test,(void*)&s1);//建立3個線程

  81.         }


  82.         for(i = 0;i<3;i++)

  83.         {

  84.                 pthread_join( *(tid+i) , NULL);//堵塞回收線程

  85.         }

  86.         pthread_mutex_destroy(&pmut);

  87.         munmap(p,MMSIZE);


  88. }

同時我們也觀察到了線程由于失去CPU而放棄執(zhí)行其他線程得到CPU繼續(xù)執(zhí)行,由于
我們使用MUTEX保護(hù)臨界區(qū)這個數(shù)數(shù)還是正常進(jìn)行。最后正常數(shù)到了150
Thread:140545405572864 work now!!!
:32:32:32:32:32:32:32:32:32:32:32:32:32:32:32:32
Thread:140545397180160 work now!!! (線程140545405572864 失去CPU線程140545397180160執(zhí)行)
:33:33:33:33:33:33:33:33:33:33:33:33:33:33:33:33
..................
Thread:140545397180160 work now!!!
:58:58:58:58:58:58:58:58:58:58:58:58:58:58:58:58
Thread:140545405572864 work now!!!(線程140545405572864重新獲得CPU)
:59:59:59:59:59:59:59:59:59:59:59:59:59:59:59:59
............
Thread:140545388787456 work now!!!
:150:150:150:150:150:150:150:150:150:150:150:150:150:150:150:150

到此,相信大家對“LINUX中的mmap是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI