首页 > 编程知识 正文

从内核态拷贝到用户态的函数,createfile函数详解

时间:2023-05-03 09:00:03 阅读:60408 作者:290

在测试文件映射的创建和打开时,经常出现“句柄无效”错误。 仔细查看MSDN后,我发现函数无法识别。 在这里翻译相关的说明

手动创建文件映射(

HANDLE hFile,//物理文件句柄

LP security _ attributeslpattributes,//安全设置

DWORD flProtect,//保护设置

DWORD dwMaximumSizeHigh,//顶级文件大小

DWORD dwMaximumSizeLow,//子文件大小

LPCTSTR lpName //共享内存名称

);

1 )物理文件句柄

如果需要创建不依赖于物理文件的存储器映射,则可获得的物理文件句柄可以设置为0xfffffff(invalid_handle_value )。

如果需要与物理文件关联,请确保创建物理文件时的访问模式与“保护设置”匹配。 例如,如果:物理文件是只读的,并且内存映射需要读写,则会发生错误。 建议以独占方式创建物理文件。

如果使用INVALID_HANDLE_VALUE,则还必须设置需要申请的内存空间的大小,无论物理文件句柄的参数是否有效。 这样,无论物理文件的大小如何,CreateFileMapping都可以创建超过实际文件大小的内存空间。 如果物理文件有效,则大小参数为0。 返回的内存空间地址范围与物理文件大小相同。 返回的文件映射的地址空间通过复制、集成或命名获得,初始内容为0。

2 )保护设置

虽然是安全设置,但通常设置为NULL即可,使用默认的安全设置。 如果windows2k需要限制,请考虑限制将内存文件映射用于在整个网络上共享的APP应用程序进程。

3 )上级文件大小

树叶们,我想现在我们的机器是32位的东边。 32位进程不能得到可寻址的专用32位地址空间。 一般设定为0吧。 我不打算把那个设定为超过0的状况。

4 )下级文件大小

这个还可以设置,但是为了让其他共享用户知道有关你申请的文件映射的信息,我在获取的地址空间的开头添加了结构化描述信息,记录了内存映射的大小、名称等,实际申请的空间比输入的空间要多我觉得像这样BSTR这样的方式很合理。

5 )共享内存名称

这是我今天测试时撞到墙上的灾难。 为了对内存的互斥访问,我设置了互斥句柄。 您选择了与共享内存相同的名称。 在这之后,由于他们使用了共同的namespace而发生了错误。 呵呵。

7 )调用CreateFileMapping时GetLastError的对应错误

如果尝试创建长度为零的ERROR_FILE_INVALID文件映射,则必须使用此报告

ERROR_INVALID_HANDLE如果发现您的名称内存空间与现有内存映射、互斥量、信号量和临界区域同名,那就麻烦了

ERROR_ALREADY_EXISTS表示内存空间的名称已经存在

8 )相关服务或平台的命名保留

终端服务:

命名时,全局或会话名称空间的主文件映射可以包含" Global "或" Local "前缀。 其他部分可以包含()以外的字符。 请参阅Kernel Object Name Spaces。

Windows 2000 or later:

如果终端服务没有执行“Global”和“Local”前缀的特殊含义,将被忽略

2

在开发软件的过程中,经常会遇到在进程之间共享数据的需求。 例如,a进程生成计算数据,b进程生成显示数据的图形。 这种开发方式可以将一个大程序分成独立的小程序,提高软件的成功率,适合与团队一起开发,加快软件的开发速度。 使用文件映射共享数据吧。 首先,使用函数CreateFileMapping创建要共享的文件数据句柄,然后使用MapViewOfFile获取共享内存地址,然后使用OpenFileMapping函数在其他进程中打开共享文件的名称函数CreateFileMapping、MapViewOfFile声明如下: winbaseapi _ _ outhandlewinapicreatefilemappinga (_ _ inhandlehfile,__in_ )。

  __in     DWORD dwMaximumSizeHigh,     __in      DWORD dwMaximumSizeLow,     __in_opt LPCSTR lpName     ); WINBASEAPI __out HANDLE WINAPI CreateFileMappingW(     __in     HANDLE hFile,     __in_opt LPSECURITY_ATTRIBUTES lpFileMappingAttributes,     __in     DWORD flProtect,     __in     DWORD dwMaximumSizeHigh,     __in     DWORD dwMaximumSizeLow,     __in_opt LPCWSTR lpName     ); #ifdef UNICODE #define CreateFileMapping CreateFileMappingW #else #define CreateFileMapping CreateFileMappingA #endif // !UNICODE WINBASEAPI __out LPVOID WINAPI MapViewOfFile(     __in HANDLE hFileMappingObject,     __in DWORD dwDesiredAccess,     __in DWORD dwFileOffsetHigh,     __in DWORD dwFileOffsetLow,     __in SIZE_T dwNumberOfBytesToMap     ); hFile 是创建共享文件的句柄。 lpFileMappingAttributes 是文件共享的属性。 flProtect 是当文件映射时读写文件的属性。 dwMaximumSizeHigh 是文件共享的大小高位字节。 dwMaximumSizeLow 是文件共享的大小低位字节。 lpName 是共享文件对象名称。 hFileMappingObject 是共享文件对象。 dwDesiredAccess 是文件共享属性。 dwFileOffsetHigh 是文件共享区的偏移地址。 dwFileOffsetLow 是文件共享区的偏移地址。 dwNumberOfBytesToMap 是共享数据长度。 调用函数的例子如下: #001   // 文件共享。 #002   // 蔡军生 2007/10/27 QQ:9073204 深圳 #003   void FileMapping(void) #004   { #005         // 打开共享的文件对象。 #006         m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, #007              FALSE,_T("TestFileMap")); #008         if (m_hMapFile) #009         { #010               // 显示共享的文件数据。 #011              LPTSTR lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS, #012                   0,0,0); #013               OutputDebugString(lpMapAddr); #014         } #015         else #016         { #017               // 创建共享文件。 #018               m_hMapFile = CreateFileMapping( (HANDLE)0xFFFFFFFF,NULL, #019                   PAGE_READWRITE,0,1024,_T("TestFileMap")); #020 #021               // 拷贝数据到共享文件里。 #022               LPTSTR lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS, #023                    0,0,0); #024               std::wstring strTest(_T("TestFileMap")); #025               wcscpy(lpMapAddr,strTest.c_str());                 #026 #027               FlushViewOfFile(lpMapAddr,strTest.length()+1); #028         } #029   }

                          

 

             3

内存映射API函数CreateFileMapping创建一个有名的共享内存:
HANDLE CreateFileMapping(
HANDLE hFile,                                                                       // 映射文件的句柄,
                                                                                                   //设为0xFFFFFFFF以创建一个进程间共享的对象
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,   // 安全属性
DWORD flProtect,                                                                   // 保护方式
DWORD dwMaximumSizeHigh,                                           //对象的大小
DWORD dwMaximumSizeLow,
LPCTSTR lpName                                                                 // 必须为映射文件命名
);

与虚拟内存类似,保护方式可以是PAGE_READONLY或是PAGE_READWRITE。如果多进程都对同一共享内存进行写访问,则必须保持相互间同步。映射文件还可以指定PAGE_WRITECOPY标志,可以保证其原始数据不会遭到破坏,同时允许其他进程在必要时自由的操作数据的拷贝。

在创建文件映射对象后使用可以调用MapViewOfFile函数映射到本进程的地址空间内。

下面说明创建一个名为MySharedMem的长度为4096字节的有名映射文件:
HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF),
NULL,PAGE_READWRITE,0,0x1000,"MySharedMem");
并映射缓存区视图:
LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile,
FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);

其他进程访问共享对象,需要获得对象名并调用OpenFileMapping函数。
HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE,
FALSE,"MySharedMem");

一旦其他进程获得映射对象的句柄,可以象创建进程那样调用MapViewOfFile函数来映射对象视图。用户可以使用该对象视图来进行数据读写操作,以达到数据通讯的目的。

当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图:
if (!UnmapViewOfFile(pszMySharedMapView))
{

         AfxMessageBox("could not unmap view of file");

}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。