免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Windows環(huán)境下共享內存通信
2015-05-24 23:51:21
標簽:共享內存 進程間通訊 共享
一、引言
在Windows程序中,各個進程之間常常需要交換數(shù)據,進行數(shù)據通訊。WIN32 API提供了許多函數(shù)使我們能夠方便高效的進行進程間的通訊,通過這些函數(shù)我們可以控制不同進程間的數(shù)據交換。
進程間通訊(即:同機通訊)和數(shù)據交換有多種方式:消息、共享內存、匿名(命名)管道、郵槽、Windows套接字等多種技術?!肮蚕韮却妗保╯hared memory)可以定義為對一個以上的進程是可見的內存或存在于多個進程的虛擬地址空間。例如:如果兩個進程使用相同的DLL,只把DLL的代碼頁裝入內存一次,其他所有映射這個DLL的進程只要共享這些代碼頁就可以了;利用消息機制實現(xiàn)IPC雖然有交換的數(shù)據量小、攜帶的信息少等缺點,但由于其實現(xiàn)方便、應用靈活而廣泛應用于無須大量、頻繁數(shù)據交換的內部進程通訊系統(tǒng)之中。
二、共享內存的介紹
1、共享內存是一種最為高效的進程間通信方式,進程可以直接讀寫內存,而不需要任何數(shù)據的拷貝。
2、為了在多個進程間交換信息,內核專門留出了一塊內存區(qū),可以由需要訪問的進程將其映射到自己的私有地址空間。進程就可以直接讀寫這一塊內存而不需要進行數(shù)據的拷貝,從而大大提高效率。
3、由于多個進程共享一段內存,因此也需要依靠某種同步機制。
共享內存的特點:
三、同機進程間共享內存的實現(xiàn)
采用內存映射文件實現(xiàn)WIN32進程間的通訊:Windows中的內存映射文件的機制為我們高效地操作文件提供了一種途徑,它允許我們在WIN32進程中保留一段內存區(qū)域,把硬盤或頁文件上的目標文件映射到這段虛擬內存中。注意:在程序實現(xiàn)中必須考慮各進程之間的同步問題。
具體實現(xiàn)步驟如下:
1、服務器創(chuàng)建一個共享內存。
在服務器端進程中調用內存映射API函數(shù)CreateFileMapping創(chuàng)建一個有名字標識的共享內存。
與虛擬內存類似,保護方式參數(shù)可以是PAGE_READONLY或是PAGE_READWRITE。如果多進程都對同一共享內存進行寫訪問,則必須保持相互間同步。映射文件還可以指定PAGE_WRITECOPY標志,可以保證其原始數(shù)據不會遭到破壞,同時允許其他進程在必要時自由的操作數(shù)據的拷貝。
例:創(chuàng)建一個名為"liuker"的長度為4096字節(jié)的有名映射文件:
HANDLEhmap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE | SEC_COMMIT, 0, 0x1000, "liuker");
2、服務器映射到當前進程的地址空間。
創(chuàng)建文件映射對象后,服務器端進程調用MapViewOfFile函數(shù)映射到本進程的地址空間內。
例:映射緩存區(qū)視圖:
LPVOIDlpdata = MapViewOfFile(hmap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
3、客戶端打開一個指定的文件映射對象。
例如:
HANDLEhmapfile = OpenFileMappingA(FILE_MAP_READ, FALSE, "liuker");
4、客戶端將一個文件映射對象映射到當前應用程序的地址空間。
例如:映射緩存區(qū)視圖:
LPVOIDlpbase = MapViewOfFile(hmapfile, FILE_MAP_READ, 0, 0, 0);
5、UnmapViewOfFile撤消地址空間內的視圖。
當用戶進程結束使用共享內存后,調用UnmapViewOfFile函數(shù)以取消其地址空間內的視圖。
6、關閉映射。
四、使用文件映射實現(xiàn)共享內存。
FileMapping用于將存在于磁盤的文件放進一個進程的虛擬地址空間,并在該進程的虛擬地址空間中產生一個區(qū)域用于“存放”該文件,這個空間就叫做File View(存放在進程的虛擬內存中),系統(tǒng)并同時產生一個File MappingObject(存放于物理內存中)用于維持這種映射關系,這樣當多個進程需要讀寫那個文件的數(shù)據時,它們的FileView其實對應的都是同一個File Mapping Object,這樣做可節(jié)省內存和保持數(shù)據的同步性,并達到數(shù)據共享的目的。
當然在一個應用向文件中寫入數(shù)據時,其它進程不應該去讀取這個正在寫入的數(shù)據。這就需要進行一些同步的操作。下邊來看一下具體的API。
CreateFileMaping的用法:
HANDLECreateFileMapping( //返回FileMapping Object的句柄
HANDLE hFile,//想要產生映射的文件的句柄
LPSECURITY_ATTRIBUTESlpAttributes, //安全屬性(只對NT和2000生效)
DWORDflProtect, //保護標致
DWORD dwMaximumSizeHigh,//在DWORD的高位中存放
File MappingObject //的大小
DWORDdwMaximumSizeLow, //在DWORD的低位中存放
File MappingObject,//的大小(通常這兩個參數(shù)有一個為0)
LPCTSTR lpName//File Mapping Object的名稱。
);
1)物理文件句柄
任何可以獲得的物理文件句柄,如果你需要創(chuàng)建一個物理文件無關的內存映射也無妨,將它設置成為0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了。
如果需要和物理文件關聯(lián),要確保你的物理文件創(chuàng)建的時候的訪問模式和"保護設置"匹配,比如:物理文件只讀,內存映射需要讀寫就會發(fā)生錯誤。推薦你的物理文件使用獨占方式創(chuàng)建。
如果使用INVALID_HANDLE_VALUE,也需要設置需要申請的內存空間的大小,無論物理文件句柄參數(shù)是否有效,這樣CreateFileMapping就可以創(chuàng)建一個和物理文件大小無關的內存空間給你,甚至超過實際文件大小,如果你的物理文件有效,而大小參數(shù)為0,則返回給你的是一個和物理文件大小一樣的內存空間地址范圍。返回給你的文件映射地址空間是可以通過復制,集成或者命名得到,初始內容為0。
2)保護設置
就是安全設置,不過一般設置NULL就可以了,使用默認的安全配置。 在win2k下如果需要進行限制,這是針對那些將內存文件映射共享給整個網絡上面的應用進程使用是,可以考慮進行限制。
3)高位文件大小
32位地址空間,設置為0。
4)共享內存名稱
命名可以包含"Global"或者"Local"前綴在全局或者會話名空間初級文件映射。其他部分可以包含任何除了()以外的字符,可以參考KernelObject Name Spaces。
5)調用CreateFileMapping的時候GetLastError的對應錯誤
ERROR_FILE_INVALID如果企圖創(chuàng)建一個零長度的文件映射,應有此報
ERROR_INVALID_HANDLE如果發(fā)現(xiàn)你的命名內存空間和現(xiàn)有的內存映射,互斥量,信號量,臨界區(qū)同名就麻煩了
ERROR_ALREADY_EXISTS表示內存空間命名已經存在
使用函數(shù)CreateFileMapping創(chuàng)建一個想共享的文件數(shù)據句柄,然后使用MapViewOfFile來獲取共享的內存地址,然后使用OpenFileMapping函數(shù)在另一個進程里打開共享文件的名稱,這樣就可以實現(xiàn)不同的進程共享數(shù)據。
附錄:示例
這個程序包括一個客戶端和一個服務端,服務端創(chuàng)建共享內存,客戶端打開共享內存,兩者通過兩個事件互斥訪問共享內存,實現(xiàn)一個小功能,就是服務端進程從控制臺讀入數(shù)據發(fā)送給客戶端進程。
服務器端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#defineFileMapping_NAME "liuker"
#define  FILESIZE 4096
LPVOIDlpdata = NULL;//指針標識首地址
voidmain()
{
if (lpdata != NULL)
{
puts("共享內存存在!\n");
}
//創(chuàng)建一個有名字標識的共享內存。
HANDLE hmap =CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT, 0,FILESIZE, FileMapping_NAME);
if (hmap == NULL)
{
puts("創(chuàng)建內存共享失敗!\n");
}
else
{
//映射文件到指針
lpdata = MapViewOfFile(hmap,FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
if (lpdata == NULL)
{
printf("服務器映射失敗!\n");
}
else
{
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8,9, 10 };
memcpy(lpdata, a, 40);
}
}
system("pause");
UnmapViewOfFile(lpdata);//解除
CloseHandle(hmap);
system("pause");
}
客戶端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#defineFileMapping_NAME "liuker"
voidmain()
{
//打開一個指定的文件映射對象,獲得共享內存對象的句柄
HANDLE hmapfile =OpenFileMappingA(FILE_MAP_READ, FALSE, FileMapping_NAME);
if (hmapfile == NULL)
{
printf("打開文件映射對象失敗!\n");
}
else
{
//將一個文件映射對象映射到當前應用程序的地址空間。
LPVOID lpbase = MapViewOfFile(hmapfile,FILE_MAP_READ, 0, 0, 0);
if (lpbase == NULL)
{
printf("映射失?。n");
}
else
{
int *p = lpbase;
for (int i = 0; i < 10; i++)
{
printf("%d\n", p[i]);
}
}
UnmapViewOfFile(lpbase);//解除映射
CloseHandle(hmapfile);//一個指定的文件映射對象
system("pause");
}
}
附錄:函數(shù)說明
1、CreateFileMapping函數(shù):
HANDLECreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTESlpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);
參數(shù)
(1)hFile
映射文件的句柄,若設為0xFFFFFFFF(即:INVALID_HANDLE_VALUE)則創(chuàng)建一個進程間共享的對象
(2)lpFileMappingAttributes
SECURITY_ATTRIBUTES,它指明返回的句柄是否可以被子進程所繼承,指定一個安全對象,在創(chuàng)建文件映射時使用。如果為NULL(用ByVal As Long傳遞零),表示使用默認安全對象。
(3)flProtect
保護文件視圖。
a.PAGE_READONLY以只讀方式打開映射
b.PAGE_READWRITE以可讀、可寫方式打開映射
c.PAGE_WRITECOPY為寫操作留下備份
可組合使用下述一個或多個常數(shù):
a.SEC_COMMIT為文件映射一個小節(jié)中的所有頁分配內存
b.SEC_IMAGE文件是個可執(zhí)行文件
c.SEC_RESERVE為沒有分配實際內存的一個小節(jié)保留虛擬內存空間
(4)dwMaximumSizeHigh
文件映射的最大長度的高32位。
(5)dwMaximumSizeLow
文件映射的最大長度的低32位。如這個參數(shù)和dwMaximumSizeHigh都是零,就用磁盤文件的實際長度。
(6)lpName
映射文件名,即共享內存的名稱。
返回值
返回的句柄,如果函數(shù)是成功的文件映射對象;否則,返回NULL。為了獲取更多的錯誤信息,調用GetLastError。
如果對象存在的函數(shù)調用之前,該函數(shù)返回的句柄,其目前的大小,而不是指定的大小現(xiàn)有的對象,GetLastError返回ERROR_ALREADY_EXISTS。
如果dwMaximumSizeLow設置為零,GetLastError返回ERROR_INVALID_PARAMETER。
2、MapViewOfFile函數(shù):
LPVOIDMapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberOfBytesToMap
);
參數(shù)
(1)hFileMappingObject
CreateFileMapping函數(shù)返回一個文件映射對象的打開的句柄。
(2)dwDesiredAccess
映射對象的文件數(shù)據的訪問方式,與CreateFileMapping()函數(shù)所設置的保護屬性相匹配。
a.FILE_MAP_WRITE映射可讀可寫。文件映射對象必須通過PAGE_READWRITE訪問創(chuàng)建。
B.FILE_MAP_READ映射只讀。文件映射對象必須通過PAGE_READ 或 PAGE_READWRITE訪問創(chuàng)建。
C.FILE_MAP_ALL_ACCESS與FILE_MAP_WRITE相同。
d.FILE_MAP_COPY映射時保留寫操作的副本。文件映射對象必須用PAGE_WRITECOPY訪問在win95下創(chuàng)建。
(3)dwFileOffsetHigh
文件中映射起點的高32位地址
(4)dwFileOffsetLow
文件中映射起點的低32位地址
(5)dwNumberOfBytesToMap
文件中要映射的字節(jié)數(shù)。用零映射整個文件映射對象。
返回值
映射視圖的起始地址表示成功;否則,返回NULL。
3、OpenFileMapping函數(shù):
HANDLEWINAPI OpenFileMapping(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ LPCTSTR lpName
);
參數(shù)
(1)dwDesiredAccess
訪問文件映射對象的安全描述。FILE_MAP_ALL_ACCESS、FILE_MAP_EXECUTE、FILE_MAP_READ、FILE_MAP_WRITE
(2)bInheritHandle
如果這個參數(shù)為TRUE,通過CreateProcess函數(shù)創(chuàng)建一個進程可以繼承句柄;否則,手柄不能被繼承。
(3)lpName
文件映射對象的名稱。可以有一個"Global\" or "Local\"前綴全局或會話名稱空間中明確打開一個對象
返回值
如果函數(shù)成功,返回值是打開的句柄到指定的文件映射對象。
如果函數(shù)失敗,返回值為NULL。
轉載于http://blog.sina.com.cn/s/blog_61ed3bc70102vmlc.html
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
內存映射
共享內存的使用
VC++ 中使用內存映射文件處理大文件
文件內存映射函數(shù)說明及應用
C++使用共享內存實現(xiàn)進程間通信
用MapViewOfFile處理大文件-內存不足
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服