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

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

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

      Windows進程通信 -- 共享內存(1)

      共享內存的方式原理就是將一份物理內存映射到不同進程各自的虛擬地址空間上,這樣每個進程都可以讀取同一份數據,從而實現進程通信。因為是通過內存操作實現通信,因此是一種最高效的數據交換方法。

      共享內存在 Windows 中是用 FileMapping 實現的,從具體的實現方法上看主要通過以下幾步來實現:

      1、調用 CreateFileMapping 創建一個內存文件映射對象;

      HANDLE CreateFileMapping(
        HANDLE hFile,              // handle to file to map
        LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
                                   // optional security attributes
        DWORD flProtect,           // protection for mapping object
        DWORD dwMaximumSizeHigh,   // high-order 32 bits of object size
        DWORD dwMaximumSizeLow,    // low-order 32 bits of object size
        LPCTSTR lpName             // name of file-mapping object
      );

      通過這個API函數 將創建一個內存映射文件的內核對象,用于映射文件到內存。與虛擬內存一樣,內存映射文件可以用來保留一個地址空間的區域,并將物理存儲器提交
      給該區域。它們之間的差別是,物理存儲器來自一個已經位于磁盤上的文件,而不是系統的頁文件。

      hFile用于標識你想要映射到進程地址空間中的文件句柄。該句柄可以通過調用C r e a t e F i l e函數返回。這里,我們并不需要一個實際的文件,所以,就不需要調用 CreateFile 創建一個文件, hFile 這個參數可以填寫 INVALID_HANDLE_VALUE; 
      
      lpFileMappingAttributes:參數是指向文件映射內核對象的 SECURITY_ATTRIBUTES結構的指針,通常傳遞的值是 N U L L;
      
      flProtect:對內存映射文件的安全設置(PAGE_READONLY 以只讀方式打開映射;PAGE_READWRITE 以可讀、可寫方式打開映射;PAGE_WRITECOPY 為寫操作留下備份)
      
      dwMaximumSizeHigh:文件映射的最大長度的高32位。
      
      dwMaximumSizeLow:文件映射的最大長度的低32位。如這個參數和dwMaximumSizeHigh都是零,就用磁盤文件的實際長度。
      
      lpName:指定文件映射對象的名字,別的進程就可以用這個名字去調用 OpenFileMapping 來打開這個 FileMapping 對象。
       
      如果創建成功,返回創建的內存映射文件的句柄,如果已經存在,則也返回其句柄,但是調用 GetLastError()返回的錯誤碼是:183(ERROR_ALREADY_EXISTS),如果創建失敗,則返回NULL;

      2、調用 MapViewOfFile 映射到當前進程的虛擬地址上;

      如果調用CreateFileMapping成功,則調用MapViewOfFile函數,將內存映射文件映射到進程的虛擬地址中;

      LPVOID MapViewOfFile(
        HANDLE hFileMappingObject,  // file-mapping object to map into 
                                    // address space
        DWORD dwDesiredAccess,      // access mode
        DWORD dwFileOffsetHigh,     // high-order 32 bits of file offset
        DWORD dwFileOffsetLow,      // low-order 32 bits of file offset
        DWORD dwNumberOfBytesToMap  // number of bytes to map
      );
       
      hFileMappingObject:CreateFileMapping()返回的文件映像對象句柄。
      dwDesiredAccess: 映射對象的文件數據的訪問方式,而且同樣要與CreateFileMapping()函數所設置的保護屬性相匹配。
      dwFileOffsetHigh: 表示文件映射起始偏移的高32位.
      dwFileOffsetLow: 表示文件映射起始偏移的低32位.
      dwNumberOfBytesToMap :文件中要映射的字節數。為0表示映射整個文件映射對象。

      3、在接收進程中打開對應的內存映射對象

      在數據接收進程中,首先調用OpenFileMapping()函數打開一個命名的文件映射內核對象,得到相應的文件映射內核對象句柄hFileMapping;如果打開成功,則調用MapViewOfFile()函數映射對象的一個視圖,將文件映射內核對象hFileMapping映射到當前應用程序的進程地址,進行讀取操作。(當然,這里如果用CreateFileMapping也是可以獲取對應的句柄)

      HANDLE OpenFileMapping(
        DWORD dwDesiredAccess,  // access mode
        BOOL bInheritHandle,    // inherit flag
        LPCTSTR lpName          // pointer to name of file-mapping object
      );
       
      dwDesiredAccess:同MapViewOfFile函數的dwDesiredAccess參數
      bInheritHandle :如這個函數返回的句柄能由當前進程啟動的新進程繼承,則這個參數為TRUE。
      lpName :指定要打開的文件映射對象名稱。

      4、進行內存映射文件的讀寫

      一旦MapViewOfFile調用成功,就可以像讀寫本進程地址空間的內存區一樣,進行內存的讀寫操作了。

      //讀操作:
      if ( m_pViewOfFile  )
      {
              // read text from memory-mapped file
              TCHAR s[dwMemoryFileSize];
              
              lstrcpy(s, (LPCTSTR) m_pViewOfFile);
      }
      //寫操作:
      if ( m_pViewOfFile )
       {
              TCHAR s[dwMemoryFileSize];
              m_edit_box.GetWindowText(s, dwMemoryFileSize);
                  
              lstrcpy( (LPTSTR) m_pViewOfFile, s);
                  
              // Notify all running instances that text was changed
              ::PostMessage(HWND_BROADCAST, 
                  wm_Message,     
                  (WPARAM) m_hWnd,
                  0);    
      }

      5、清理內核對象

      在用完后,要取消本進程地址空間的映射,并釋放內存映射對象。

          //取消本進程地址空間的映射;   
          UnmapViewOfFile(pLocalMem);  
            
          pLocalMem=NULL;   
          //關閉文件映射內核文件  
          CloseHandle(hFileMapping);

      6、簡單例子

      下面寫一個簡單的例子來說明:

      例子:在一個進程的文本對話框中輸入文本,同時在另一個進程的文本對話框中顯示之前輸入的內容。

      const DWORD dwMemoryFileSize = 4 * 1024;  //指定內存映射文件大小
      
      const LPCTSTR sMemoryFileName = _T("D9287E19-6F9E-45fa-897C-D392F73A0F2F");//指定內存映射文件名稱
      
      const UINT    wm_Message = 
          RegisterWindowMessage(_T("CC667211-7CE9-40c5-809A-1DA48E4014C4"));//注冊消息

      指定消息處理函數

      BEGIN_MESSAGE_MAP(CIpcDlg, CDialog)
          //{{AFX_MSG_MAP(CIpcDlg)
          ON_WM_SYSCOMMAND()
          ON_WM_PAINT()
          ON_WM_QUERYDRAGICON()
          ON_WM_DESTROY()
          ON_REGISTERED_MESSAGE(wm_Message, OnMessageTextChanged)
          ON_EN_CHANGE(IDC_EDT_TEXT, OnChangeEdtText)
          //}}AFX_MSG_MAP
      END_MESSAGE_MAP()
       

      LRESULT CIpcDlg::OnMessageTextChanged( WPARAM wParam, LPARAM lParam )
      {
          if ( wParam == (WPARAM) m_hWnd )
              return 0;
         
          // Get text from memory mapped file and set it to edit box
          GetTextFromMemoryMappedFile();
         
          return 0;
      }

      窗口初始化函數中進行內存映射文件的初始化:

      void CIpcDlg::Initialize()
      {
          m_edit_box.SetLimitText(dwMemoryFileSize - 1);
          m_hFileMapping = CreateFileMapping(
              INVALID_HANDLE_VALUE,           // system paging file
              NULL,                           // security attributes
              PAGE_READWRITE,                 // protection
              0,                              // high-order DWORD of size
              dwMemoryFileSize*sizeof(TCHAR), // low-order DWORD of size
              sMemoryFileName);               // name
          DWORD dwError = GetLastError();     // if ERROR_ALREADY_EXISTS 
          // this instance is not first (other instance created file mapping)
          
          if ( ! m_hFileMapping )
          {
              MessageBox(_T("Creating of file mapping failed"));
          }
          else
          {
              m_pViewOfFile = MapViewOfFile(
                  m_hFileMapping,             // handle to file-mapping object
                  FILE_MAP_ALL_ACCESS,        // desired access
                  0,
                  0,
                  0);                         // map all file
              
              if ( ! m_pViewOfFile )
              {
                  MessageBox(_T("MapViewOfFile failed"));
              }
              
              // Now we have m_pViewOfFile memory block which is common for
              // all instances of this program
          }
          
          if ( dwError == ERROR_ALREADY_EXISTS )
          {
              // Some other instance is already running,
              // get text from existing file mapping
              GetTextFromMemoryMappedFile();
          }
      }

      內存映射對象內容的讀取及顯示:

      void CIpcDlg::GetTextFromMemoryMappedFile()
      {
          if ( m_pViewOfFile  )
          {
              // read text from memory-mapped file
              TCHAR s[dwMemoryFileSize];
              
              lstrcpy(s, (LPCTSTR) m_pViewOfFile);
              
              // Write text to edit box.
              // SetWindowText raises EN_CHANGE event and
              // OnChangeEditBox is called. Ensure that OnChangeEditBox
              // does nothing by setting m_bNotify to FALSE
              m_bNotify = FALSE;  
              
              m_edit_box.SetWindowText(s);    
              
              m_bNotify = TRUE;
          }
      }

      在文本框的OnChangeEdtText事件中寫內存映射文件,并發wm_Message 進行通知:

      void CIpcDlg::OnChangeEdtText() 
      {
          if ( m_bNotify)        // change is not done by SetWindowText
          {
              // write text to memory-mapped file
              if ( m_pViewOfFile )
              {
                  TCHAR s[dwMemoryFileSize];
                  m_edit_box.GetWindowText(s, dwMemoryFileSize);
                  
                  lstrcpy( (LPTSTR) m_pViewOfFile, s);
                  
                  // Notify all running instances that text was changed
                  ::PostMessage(HWND_BROADCAST, 
                      wm_Message,     
                      (WPARAM) m_hWnd,
                      0);    
              }
          }
          
      }

      image

      至此,一個最簡單的通過內存映射文件的進程通信的例子就完成了,但是這里存在一個問題:讀和寫之間的沖突沒有很好的解決,內存映射文件是一個共享的資源,多個進程讀寫必然存在同步的問題,也許在這個例子中不會出現什么問題,但是實際項目中存在較高頻率的并發讀寫的情況下,如何進行同步是一個必須解決的問題,未完待續…

      posted @ 2014-10-11 11:05  紅心李  閱讀(28326)  評論(9)    收藏  舉報
      主站蜘蛛池模板: 国产中年熟女高潮大集合| 国产色视频网站免费| 老熟女重囗味hdxx69| 北条麻妃一区二区三区av高清| 我要看特黄特黄的亚洲黄片| 国产乱码1卡二卡3卡四卡5| 免费国产一区二区不卡| 国产精品中文字幕在线| 国产99视频精品免费视频36| 亚洲二区中文字幕在线| 国产精品国产三级在线专区| 国产成人高清亚洲综合| 国产国产午夜福利视频| 久久人妻公开中文字幕| 色综合久久精品中文字幕| 宝贝腿开大点我添添公视频免| 97人人超碰国产精品最新| 亚洲欧洲日产国无高清码图片| 亚洲精品男男一区二区| 日本一卡2卡3卡4卡无卡免费| 国产精品白丝久久AV网站| 亚洲精品一区二区三区免| 最新精品露脸国产在线| 成人自拍小视频免费观看| 怡红院一区二区三区在线| 在线观看国产精品日韩av | 色午夜久久男人操女人| 草草浮力影院| 狠狠色狠狠色综合日日不卡| 女主播扒开屁股给粉丝看尿口| 人妻少妇精品性色av蜜桃| 国产精品自拍午夜福利| 热久久这里只有精品国产| 亚洲国产欧美在线人成大黄瓜| 国产AV巨作丝袜秘书| 亚洲天堂一区二区成人在线| 欧美日本激情| 国产综合亚洲区在线观看| 成人午夜大片免费看爽爽爽| 国产精品制服丝袜无码| 国产综合有码无码中文字幕|