<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      eaglet

      本博專注于基于微軟技術的搜索相關技術
        博客園  :: 首頁  :: 新隨筆  :: 聯系 :: 訂閱 訂閱  :: 管理

      讓.Net 應用程序突破2G的內存訪問限制

      Posted on 2008-11-06 14:00  eaglet  閱讀(10404)  評論(17)    收藏  舉報

      讓.Net 應用程序突破2G的內存訪問限制

       Author: Eaglet

          32位Windows操作系統下單個進程的用戶模式內存訪問的限制是2G,如果在boot.ini中設置了/3G開關,則最大為3G,超過3G將無法訪問。由于Hubble.net 項目是一個數據庫系統,必須要考慮使用大內存緩存數據的問題,于是最近對這個問題進行了一些研究。其實這塊的技術是現成的,32位操作系統下只有通過AWE的方式來擴展內存。這塊的文章也很多,但很少有.net 下如何使用的實例,我做了一個類似MemoryStream的封裝,可以讓.Net程序員輕松操作AWE內存,從而使其程序輕松突破2G內存的限制。

           在開始這篇文章之前,我們還是先來了解一下AWE.

           AWE (Address Windowing Extensions)是 Windows 的內存管理功能的一組擴展,它使應用程序能夠使用的內存量超過通過標準 32 位尋址可使用的 2-3 GB 內存。AWE 允許應用程序獲取物理內存,然后將非分頁內存的視圖動態映射到 32 位地址空間。雖然 32 位地址空間限制為 4 GB,但是非分頁內存卻可以遠遠大于 4 GB。這使需要大量內存的應用程序(如大型數據庫系統)能使用的內存量遠遠大于 32 位地址空間所支持的內存量。

          

           如上圖所示AWE 實際上就是將用戶模式下的32位內存地址映射到用戶需要訪問的物理內存上去。不同操作系統運行被映射的物理內存大小是不一樣的。

           Vista, XP 和 Windows 2003 標準版 最多可以映射 4G 內存。

           Windows 2003 企業版的限制是32G (要使用超過4G的內存必須打開 /PAE 開關

           Windows 2003 數據中心版本限制是64G (要使用超過4G的內存必須打開 /PAE 開關

           由于被映射的物理內存為不分頁內存,無法進行頁保護,為了保證內存使用的安全,防止其他進程越界訪問,AWE 在映射這些內存之前必須將這些內存鎖定,即只有鎖定這塊內存的進程可以訪問這塊內存,其它進程無法訪問。這里就產生了一個有趣的現象,我們可以在windows 下像實時操作系統那樣操作物理內存,而不用擔心操作系統進行頁交換時對系統實時性的影響。雖然不采用AWE,也可以通過VirtualLock API函數來鎖定物理內存,但這個函數在一個進程中最多可以鎖定30個頁面,以一個頁大小4096來計算,最多可以鎖定30*4094字節的內存。當然這是默認設置,你也可以通過調整工作 WorkingSet 來調整??磥鞟WE對于那些實時性比較高的應用,比如游戲,動畫,通訊等還確實是一個福音。

           由于需要鎖定物理內存,所以運行AWE功能的程序,必須要具備鎖定內存的權限,系統管理員帳號是沒有這個權限的,只有 System帳號有這個權限。當然你也可以在本地安全設置中指定某個帳號擁有這個權限。方法如下:

       

      gpedit.msc ->Windows Settings->Security Settings->Local Policies->User Rights Assignment->Lock pages in memory

       

           談完鎖定內存的問題,我們再看看上面那個圖,我們會發現雖然AWE允許訪問最多64G的內存,但這64G內存是被AWE映射到一個32位的用戶模式下的內存地址中去的,也就是說通常情況下,我們最多可以同時訪問64G內存中的2G內存 (如果配置了/3G開關,可以同時訪問最多16G內存中的3G內存),如果要訪問整個64G的內存,我們需要將一些不訪問的內存取消映射,這樣可以空出足夠的用戶模式下的虛擬內存地址來訪問我們需要訪問的內存。因此我封裝的類中添加了Map和UnMap兩個方法,讓調用者可以根據實際情況來決定映射和去映射。2G的32位虛擬內存地址對于我們來是是如此的寶貴,調用者在貪婪的消耗大量內存時一定要注意節約這個資源。

           談完這些東西,下面讓我們結合代碼來看看在.Net 下如何來操作AWE 內存吧。

           為了方便.Net 程序員訪問AWE內存,我封裝了一個AweStream類,這個類繼承自Stream類。.Net程序員可以像操作普通的MemoryStream流那樣操作AWE內存。同時我還為那些對效率要求非常苛刻的調用者提供了一個通過指針訪問AWE內存的方法。

           調用示例如下:注意必須在構造函數中指明申請的AWE內存的大小。

                      byte[] inputBuffer = new byte[1024];

                      Stopwatch stopWatch 
      = new Stopwatch();

                      
      using (AweStream.AweStream aweStream = new AweStream.AweStream(1024 * 1024 * 100))
                      
      {
                          
      //Map
                          aweStream.Map();
                          stopWatch.Start();

                          
      //Copy one bytes
                          
      //Use unsafe pointer
                          for (int i = 0; i < 1024 * 1024 * 100; i++)
                          
      {
                              
      unsafe
                              
      {
                                  aweStream.LpMemory[i] 
      = 1;
                              }

                          }


                          stopWatch.Stop();

                          Console.WriteLine(stopWatch.ElapsedMilliseconds);

                          aweStream.Position 
      = 0;

                          
                          
      //Block copy
                          stopWatch.Reset();
                          stopWatch.Start();

                          
      for (int i = 0; i < 1024 * 100; i++)
                          
      {
                              
      unsafe
                              
      {
                                  aweStream.Write(inputBuffer, 
      01024);
                              }

                          }


                          stopWatch.Stop();

                          Console.WriteLine(stopWatch.ElapsedMilliseconds);

                          
      //UnMap
                          aweStream.UnMap();
                      }

       

       我在 6G內存 windows 2003 企業版的環境中做了測試,申請內存到5G以上沒有任何問題。

       下面再看看如何來申請AWE內存

       下面的AweStream構造函數完成了對AWE內存的申請過程。

       整個申請過程分為下面幾步

       1、為當前進程申請鎖定內存的權限(注意 調用進程的帳號必須具備鎖定內存的權限,否則這一步會失

       2、就是需要申請的頁面數量

       3、通過 AllocateUserPhysicalPages API 申請AWE內存

       

              public AweStream(UInt32 capacity)
              
      {
                  
      unsafe
                  
      {
                      
      // Enable the privilege of lock memory.

                      
      lock (_SetLockPagesPrivilegeLockObj)
                      
      {
                          
      if (!_SetLockPagesPrivilegeOk)
                          
      {
                              LoggedSetLockPagesPrivilege.SetLockPagesPrivilege(System.Diagnostics.Process.GetCurrentProcess(), 
      true);
                              _SetLockPagesPrivilegeOk 
      = true;
                          }

                      }


                      General.SYSTEM_INFO sysInfo;
                      General.GetSystemInfo(
      out sysInfo);  // fill the system information structure

                      _PageSize 
      = sysInfo.dwPageSize;
                      
      if ((capacity % _PageSize) != 0)
                      
      {
                          _NumberOfPages 
      = capacity / _PageSize + 1;
                      }

                      
      else
                      
      {
                          _NumberOfPages 
      = capacity / _PageSize;
                      }


                      _PFNArraySize 
      = (UInt32)(_NumberOfPages * sizeof(UInt64*));               // memory to request for PFN array

                      _PFNArray 
      = Marshal.AllocHGlobal((int)_PFNArraySize);

                      UInt32 numberOfPagesInitial 
      = _NumberOfPages;

                      
      if (!AweApi.AllocateUserPhysicalPages(System.Diagnostics.Process.GetCurrentProcess().Handle,
                          
      ref _NumberOfPages, _PFNArray))
                      
      {
                          Dispose();
                          
      throw new AweStreamException("Cannot allocate physical pages", AweStreamException.Reason.CannotAllocatePhysicalPages);
                      }


                      _AweAllocated 
      = true;

                      
      if (numberOfPagesInitial != _NumberOfPages)
                      
      {
                          Dispose();
                          
      throw new AweStreamException(string.Format("Allocated only {0} pages.", _NumberOfPages),
                               AweStreamException.Reason.AweMemoryNotEnough);
                      }


                      _Capacity 
      = _PageSize * _NumberOfPages;
                  }


              }

       

      AWE內存申請完畢后并不能被立即訪問到,我們必須將其映射到32位內存地址中才可以訪問。

      下面是內存映射的代碼:

      也很簡單:

      首先先通過VirtualAlloc函數申請一塊32位虛擬內存區域

      然后通過 MapUserPhysicalPages API 函數將AWE內存映射到這個虛擬內存地址區域。

       

       

       

              public void Map(bool readOnly)
              {
                  
      unsafe
                  {
                      
      if (IsMapped)
                      {
                          
      return;
                      }

                      
      if (readOnly)
                      {
                          _VirtualAddress 
      = AweApi.VirtualAlloc(null, Capacity, AweApi.MEM_RESERVE | AweApi.MEM_PHYSICAL,
                                              AweApi.PAGE_READONLY);
                      }
                      
      else
                      {
                          _VirtualAddress 
      = AweApi.VirtualAlloc(null, Capacity, AweApi.MEM_RESERVE | AweApi.MEM_PHYSICAL,
                                              AweApi.PAGE_READWRITE);
                      }

                      
      if (_VirtualAddress == null)
                      {
                          
      throw new AweStreamException("Cannot reserve memory.", AweStreamException.Reason.CannotReserveMemory);
                      }

                      
      if (!AweApi.MapUserPhysicalPages(_VirtualAddress, _NumberOfPages, _PFNArray))
                      {
                          AweApi.VirtualFree(_VirtualAddress, Capacity, AweApi.MEM_RELEASE);
                          _VirtualAddress 
      = null;
                          
      throw new AweStreamException(string.Format("MapUserPhysicalPages failed ({0})", General.GetLastError()),
                              AweStreamException.Reason.MapUserPhysicalPagesFail);
                      }

                      _CanWrite 
      = !readOnly;
                  }
              }

         

       去映射和歸還AWE內存的過程是上面兩個過程的逆過程,這里就不再多講,有興趣可以看我的代碼。

      下面是實例代碼下載位置

      源代碼地址

       

       

       

      主站蜘蛛池模板: 亚洲鸥美日韩精品久久| 在线日韩日本国产亚洲| 国产成人无码区免费内射一片色欲 | 91精品一区二区蜜桃| 在线观看的网站| 五月天丁香婷婷亚洲欧洲国产| 在线观看美女网站大全免费| 国产精品中文字幕自拍| 人妻少妇乱子伦精品无码专区电影| 亚洲人成小说网站色在线| 国产av一区二区午夜福利| 老色99久久九九爱精品| 欧美精品亚洲精品日韩专| 盐源县| 亚洲乱码国产乱码精品精| 99久久国产一区二区三区| 久久精品人人槡人妻人人玩| 久久婷婷综合色丁香五月| 国产三级国产精品国产专| 中文字幕亚洲综合第一页| 被黑人伦流澡到高潮HNP动漫| 葫芦岛市| 伊人成色综合人夜夜久久| 亚洲国内精品一区二区| 狠狠干| 日韩在线视频线观看一区| 久久香蕉欧美精品| 免费AV手机在线观看片| 久久亚洲色www成人欧美| 狠狠亚洲狠狠欧洲2019| 高清破外女出血AV毛片| 午夜福利影院不卡影院| 男女动态无遮挡动态图| 亚洲老熟女一区二区三区| 亚洲av无码乱码在线观看野外 | 人妻蜜臀久久av不卡| 陕西省| 无码天堂亚洲国产av麻豆| 香蕉eeww99国产在线观看| 小污女小欲女导航| 亚洲一区二区中文av|