将输入文件映射到内存中,然后从映射的内存页直接解析数据可以方便有效地从文件读取数据.

但是,除非您可以确保没有其他进程对映射文件进行写入,否则这种做法也似乎是根本不安全的,因为如果底层文件由另一个进程写入,即使私有只读映射中的数据可能会更改. (POSIX例如doesn’t specify“是否可以通过MAP_PRIVATE映射查看在MAP_PRIVATE映射建立之后完成的底层对象的修改”.)

如果您希望在映射文件存在外部更改的情况下使代码安全,则只能通过volatile指针访问映射的内存,然后非常小心您如何读取和验证输入,这似乎不切实际很多用例

这个分析是否正确?内存映射API的文档通常只提及这个问题,如果有的话,我想知道我是否缺少一些东西.

解决方法

这不是一个真正的问题.

是的,另一个进程可能会在映射文件时修改文件,是的,可能会看到修改.由于几乎所有的操作系​​统都具有统一的虚拟内存系统,因此几乎所有的操作系​​统都是可以统一的,所以除非一个请求无缓冲的写入,否则没有办法通过缓冲区缓存进行写入,没有任何人没有看到变化的映射.
那甚至不是坏事.其实,如果你看不到这些变化,会更加令人不安.由于在映射文件时,文件准将成为地址空间的一部分,因此您可以看到文件的更改是完美的.

如果使用传统的I / O(如读取),则在读取文件时仍可修改文件.用不同的措辞,将文件内容复制到内存缓冲区并不总是存在修改的安全性.只要读取不会崩溃,它是“安全的”,但不能保证您的数据是一致的.
除非你使用readv,否则你不能保证原子性(甚至在readv你不能保证你在内存中的内容与磁盘上的一致,或者在两次调用readv之间都不会改变).有人可能会在两次读取操作之间修改文件,或者甚至当您处于中间时.
这不仅仅是一个没有得到正式保证的东西,而是“可能仍然有效” – 相反地,例如在Linux下的写作不是原子的.甚至偶然.

好消息:
通常,进程不只是打开任意的随机文件并开始写入它.当这样的事情发生时,它通常是属于进程的一个众所周知的文件(例如日志文件),或者你明确地告诉进程写入的文件(例如保存在文本编辑器中),或者进程创建一个新的文件(例如编译器创建一个对象文件),或者这个进程只是附加到一个现有的文件(例如数据库日志,当然还有日志文件).或者,进程可能会原子替换另一个文件(或取消链接).

在每一种情况下,整个可怕的问题归结为“没有问题”,因为您很清楚将会发生什么(因此是您的责任),否则无缝干扰就可以工作.

如果您真的不喜欢另一个进程可能在映射文件时写入文件的可能性,那么在创建文件句柄时,您可以在Windows下简单地省略FILE_SHARE_WRITE. POSIX使得它更复杂一些,因为您需要为一个强制性锁定描述符fcntl,这在每个系统(例如,在Linux下)不需要支持或100%可靠.

c – 用于读取输入文件的内存映射文件的安全性如何?的更多相关文章

  1. 《从零开始学Swift》学习笔记Day 71——Swift与C/C++混合编程之数据类型映射

    而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言相对应数据类型。代码中CUnsignedChar是将Int类型转化为C语言unsignedchar类型,在Swift中使用CUnsignedChar表示。从表可见针对C语言多样的指针形式,Swift主要通过提供了三种不安全的泛型指针类型:UnsafePointer、UnsafeMutablePointer和AutoreleasingUnsafeMutablePointer。T是泛型占位符,表示不同的数据类型。另外,还有cop

  2. 《从零开始学Swift》学习笔记Day 71――Swift与C/C++混合编程之数据类型映射

    而在Swift语言中是不能直接使用C数据类型,苹果公司为Swift语言提供与C语言相对应数据类型。代码中CUnsignedChar是将Int类型转化为C语言unsignedchar类型,在Swift中使用CUnsignedChar表示。从表可见针对C语言多样的指针形式,Swift主要通过提供了三种不安全的泛型指针类型:UnsafePointer、UnsafeMutablePointer和AutoreleasingUnsafeMutablePointer。T是泛型占位符,表示不同的数据类型。另外,还有cop

  3. Windows环缓冲区无需复制

    在RingBuffer’sWikipediaentry,有examplecode显示UNIX系统的黑客,其中相邻虚拟内存到一块内存是mapped到相同的物理内存,因此实现了一个环形缓冲区而不需要任何memcpy等.我想知道是否有办法在Windows这么类似的东西?谢谢,弗雷泽我并没有真正遵循维基百科中的示例的所有细节.考虑到这一点,您使用CreateFileMapping和MapViewOfFile在Windows中映射内存,但MapViewOfFile不允许您为映射指定基址.MapViewOfFileE

  4. DLL,内存映射,基地址,内存使用和.NET?

    .此外,我知道我们没有在我们的解决方案中查看所有.NET程序集的基址,.NET程序集是否需要这样做?如果这样就产生了大量代码,那么我们必须先看看生成的代码,以确定是否需要调整它.编辑:在这里添加一个较短的问题列表:>确保.NET程序集的基本地址是唯一的且不重叠的,以避免重新使用大部分用于仅将IL代码用于JITting的dll的任何意义?

  5. php – 在javascript中实现支持对象方法作为映射函数的映射?

    我最近尝试在javascript中使用map的实现来创建一堆项目,然后将它们应用于对象添加方法.首先是沼泽标准的地图实现.建立.而我的功能……无论如何,我的问题是,我怎样才能实现map来实际支持使用对象方法作为我的映射函数?

  6. Windows进程的内存映射如何?

    这可能是一个重复的问题.我想知道一个windows进程的内存映射怎么样?

  7. windows下进程间通信

    MicrosoftWin32API提供了多种进程间通信的方法,全面地阐述了这些方法的特点,并加以比较和分析,希望能给读者选择通信方法提供参考。MicrosoftWin32应用编程接口提供了大量支持应用程序间数据共享和交换的机制,这些机制行使的活动称为进程间通信,进程通信就是指不同进程间进行数据共享和数据交换。但剪贴板只能在基于Windows的程序中使用,不能在网络上使用。大多数基于Windows的应用程序都支持DDE。

  8. java – 域模型映射器应该是静态的吗?

    在我参与的许多项目中,我们经常会有很多类将内容从一个域模型映射到另一个域模型.例如,从WSDL生成的模型到项目特定的模型.例如这也可以是一个非静态方法,服务层可以有一个映射器对象字段,而不是调用静态方法:我发现两种方法都使用了很多,但是:>以任何方式提高效率的解决方案之一?>任何解决方案都被认为是最佳实践吗?

  9. java – 从数据库获取数据与从哈希映射获取数据

    在我的android*项目*我必须跟踪一定数量的产品的产品细节.这些产品上的所有数据都存储在sqlite数据库中.我可以在sqlite中使用select和update来跟踪产品对象.因此,我可以在更改时存储产品详细信息.此外,我可以在开始时将所有产品加载到哈希映射或此类数据结构中,并跟踪这些产品对象.对我而言,最重要的是哪一个更有效率和更高效.有人能帮我吗.谢谢!

  10. 如何在Java中映射(mmap)linux块设备(例如/ dev / sdb)?

    我可以使用java.nio读取/编写带有Java的linux块设备.以下代码有效:但是,内存映射不起作用.以下代码失败:这失败,错误:有没有解决这个问题?我在某个地方读过,可能是通过使用JNI,我可以做到这一点,但我找不到任何来源.解决方法根据documentation,实际映射文件的机制留给实现.似乎实现正在尝试截断文件(可能是因为块设备大小与您指定的大小不同?

随机推荐

  1. 从C到C#的zlib(如何将byte []转换为流并将流转换为byte [])

    我的任务是使用zlib解压缩数据包(已接收),然后使用算法从数据中生成图片好消息是我在C中有代码,但任务是在C#中完成C我正在尝试使用zlib.NET,但所有演示都有该代码进行解压缩(C#)我的问题:我不想在解压缩后保存文件,因为我必须使用C代码中显示的算法.如何将byte[]数组转换为类似于C#zlib代码中的流来解压缩数据然后如何将流转换回字节数组?

  2. 为什么C标准使用不确定的变量未定义?

    垃圾价值存储在哪里,为什么目的?解决方法由于效率原因,C选择不将变量初始化为某些自动值.为了初始化这些数据,必须添加指令.以下是一个例子:产生:虽然这段代码:产生:你可以看到,一个完整的额外的指令用来移动1到x.这对于嵌入式系统来说至关重要.

  3. 如何使用命名管道从c调用WCF方法?

    更新:通过协议here,我无法弄清楚未知的信封记录.我在网上找不到任何例子.原版的:我有以下WCF服务我输出添加5行,所以我知道服务器是否处理了请求与否.我有一个.NET客户端,我曾经测试这一切,一切正常工作预期.现在我想为这个做一个非托管的C客户端.我想出了如何得到管道的名称,并写信给它.我从here下载了协议我可以写信给管道,但我看不懂.每当我尝试读取它,我得到一个ERROR_broKEN_P

  4. “这”是否保证指向C中的对象的开始?

    我想使用fwrite将一个对象写入顺序文件.班级就像当我将一个对象写入文件时.我正在游荡,我可以使用fwrite(this,sizeof(int),2,fo)写入前两个整数.问题是:这是否保证指向对象数据的开始,即使对象的最开始可能存在虚拟表.所以上面的操作是安全的.解决方法这提供了对象的地址,这不一定是第一个成员的地址.唯一的例外是所谓的标准布局类型.从C11标准:(9.2/20)Apointe

  5. c – 编译单元之间共享的全局const对象

    当我声明并初始化一个const对象时.两个cpp文件包含此标头.和当我构建解决方案时,没有链接错误,你会得到什么如果g_Const是一个非const基本类型!PrintInUnit1()和PrintInUnit2()表明在两个编译单元中有两个独立的“g_Const”具有不同的地址,为什么?

  6. 什么是C名称查找在这里? (&GCC对吗?)

    为什么在第三个变体找到func,但是在实例化的时候,原始变体中不合格查找找不到func?解决方法一般规则是,任何不在模板定义上下文中的内容只能通过ADL来获取.换句话说,正常的不合格查找仅在模板定义上下文中执行.因为在定义中间语句时没有声明func,并且func不在与ns::type相关联的命名空间中,所以代码形式不正确.

  7. c – 在输出参数中使用auto

    有没有办法在这种情况下使用auto关键字:当然,不可能知道什么类型的.因此,解决方案应该是以某种方式将它们合并为一个句子.这可用吗?解决方法看起来您希望默认初始化给定函数期望作为参数的类型的对象.您无法使用auto执行此操作,但您可以编写一个特征来提取函数所需的类型,然后使用它来声明您的变量:然后你就像这样使用它:当然,只要你重载函数,这一切都会失败.

  8. 在C中说“推动一切浮动”的确定性方式

    鉴于我更喜欢将程序中的数字保留为int或任何内容,那么使用这些数字的浮点数等效的任意算术最方便的方法是什么?说,我有我想写通过将转换放在解析的运算符树叶中,无需将表达式转化为混乱是否可以使用C风格的宏?应该用新的类和重载操作符完成吗?解决方法这是一个非常复杂的表达.更好地给它一个名字:现在当您使用整数参数调用它时,由于参数的类型为double,因此使用常规的算术转换将参数转换为double用C11lambda……

  9. objective-c – 如何获取未知大小的NSArray的第一个X元素?

    在objectiveC中,我有一个NSArray,我们称之为NSArray*largeArray,我想要获得一个新的NSArray*smallArray,只有第一个x对象…

  10. c – Setprecision是混乱

    我只是想问一下setprecision,因为我有点困惑.这里是代码:其中x=以下:方程的左边是x的值.1.105=1.10应为1.111.115=1.11应为1.121.125=1.12应为1.131.135=1.14是正确的1.145=1.15也正确但如果x是:2.115=2.12是正确的2.125=2.12应为2.13所以为什么在一定的价值是正确的,但有时是错误的?请启发我谢谢解决方法没有理由期望使用浮点系统可以正确地表示您的帖子中的任何常量.因此,一旦将它们存储在一个双变量中,那么你所拥有的确切的一

返回
顶部