在Windows中,可以通过打开设备和卷CreateFile().我以前成功地使用过它ReadFile()来自设备,但现在我想切换到内存映射.在下面的代码中,我收到INVALID_HANDLE_VALUE的值为b,并c设置为87,ERROR_INVALID_PARAMETER.
HANDLE a = ::CreateFileA("\\\\.\\h:", GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY | FILE_FLAG_NO_BUFFERING, NULL);
HANDLE b = ::CreateFileMappingA(a, NULL, PAGE_READONLY, 0, 0, NULL);
DWORD c = ::GetLastError();
Run Code Online (Sandbox Code Playgroud)
我怎样才能让它发挥作用?
我的任务是以C#控制台应用程序的形式提供对非常大(50GB +)的ASCII文本文件(在第n行中处理第n行/第n个单词的请求)的随机读取访问.
谷歌搜索和阅读几天后,我已经达到了这样的实现愿景:由于StreamReader擅长顺序访问,使用它来构建文件中的行/单词的索引(List<List<long>>map,其中map[i][j]是第i个第j个单词的位置)线开始).然后使用索引通过MemoryMappedFile访问文件,因为它擅长提供随机访问.
解决方案中是否存在一些明显的缺陷?它对于给定的任务是否是最佳的?
UPD:它将在64位系统上执行.
我需要创建Qt5 / C ++的“ tail -5 myfile”等效项(不使用shell命令。我发现了几个stackoverflow引用,它们在文件结尾之前先查找X字节,然后再向前读取,但我希望有一些东西更好。
有可用的Qt功能更好的/更快的方法,还是文件的内存映射(一部分)?(有问题的文件可能很大,所以这必须相对提高内存效率)
无法真正找到任何细节,以下是关于mmf在windows中的所有知识:
这看起来倒退了,因为对于一个人,我知道mmf本身实际上有记忆......某处.如果我在mmf中写入内容并破坏视图,数据仍然存在.同时,为什么视图会占用任何内存?它只是一个指针,不是吗?
然后是什么怪异的事实上在公羊和什么在盘上.在具有分布式外观访问模式的大型mmf中,有时速度是存在的,有时则不是.我猜它有些存在于文件中,如果有人与它或页面文件绑在一起,但实际上,我没有任何线索.
无论如何,驱使我去研究这个的问题是我有一个~2gb文件,我希望多个程序共享.我无法在每个视图中创建一个2gb的视图,因为我只是"内存不足"所以我必须创建/销毁较小的视图.由于额外的偏移计算和视图本身的创建,这会产生大量开销.任何人都可以向我解释为什么会这样吗?
我有一个python3使用numpy.memmap数组操作的脚本.它将数组写入新生成的临时文件,该文件位于/tmp:
import numpy, tempfile
size = 2 ** 37 * 10
tmp = tempfile.NamedTemporaryFile('w+')
array = numpy.memmap(tmp.name, dtype = 'i8', mode = 'w+', shape = size)
array[0] = 666
array[size-1] = 777
del array
array2 = numpy.memmap(tmp.name, dtype = 'i8', mode = 'r+', shape = size)
print('File: {}. Array size: {}. First cell value: {}. Last cell value: {}'.\
format(tmp.name, len(array2), array2[0], array2[size-1]))
while True:
pass
Run Code Online (Sandbox Code Playgroud)
硬盘的大小只有250G.尽管如此,它可以以某种方式生成10T大文件/tmp,并且相应的数组似乎仍然可以访问.脚本的输出如下:
File: /tmp/tmptjfwy8nr. Array size: 1374389534720. …Run Code Online (Sandbox Code Playgroud) 我的意思是在不使用write()的情况下直接在内存中更新数据.
在linux中我认为在msync调用中指定的所有数据都被刷新了.
但是在Windows中,FlushViewOfFile的文档说"写脏页",所以操作系统知道哪些页面已被更新.
这是如何运作的 ?我们是否必须使用WriteFile来更新映射内存?如果我们在linux中使用write(),msync只会同步脏页吗?
我有一个 mmap
void *mymap;
mymap = mmap(0, attr.st_size, PROT_READ|PROT_WRITE, MAPFILE|MAP_SHARED, fd, 0);
Run Code Online (Sandbox Code Playgroud)
我打开了一个 HEX 内容为 0x25362364 的文件,它是
00100101001101100010001101100100
以二进制形式。现在我想执行一个位移:
char *str = (char *)mymap;
for(int i=0;i<attr.st_size;i++) {
str[i] = str[i] >> 4;
}
Run Code Online (Sandbox Code Playgroud)
我的新文件包含新的二进制数
00000010000000110000001000000110
但希望的结果是将所有内容向右移动 4 位:
00000010010100110110001000110110
我怎样才能做到这一点?奖金问题:如果二进制数 MSB 是 1,我怎样才能在向右移动时让左侧填充 0?
语境:
我正在开发一个需要快速访问大文件的应用程序,因此我使用内存映射。memcpy阅读和写作因此变得简单。我现在正在尝试添加中止任何正在进行的读取或写入的功能。
我想到的第一件事(因为我不知道任何可中断的 memcpy 函数)是定期检查memcpy几KB并检查操作是否应该中止。如果读取速度相当快,这应该可以确保近乎瞬时的中止。
如果不是,那么应用程序不应该花费很长时间才能中止,所以我的第二个想法是使用多线程。memcpy 发生在它自己的线程中,控制线程使用WaitForMultipleObjects发出中止信号的事件和 memcpy 线程。如果中止事件收到信号,它将杀死 memcpy 线程。然而,TerminateThread 的文档指出,应该绝对确保不会因为不释放资源而使系统处于不良状态。
问题:
memcpy 是否会执行任何操作,导致在复制映射内存时杀死它变得不安全?这样做安全吗?它是否依赖于实现(使用与 Windows x86-64 不同的操作系统/体系结构)?
我确实意识到使用第二种方法可能完全是矫枉过正,因为实际上没有 1KB 读/写会花费那么长时间,但我只是想安全一点。
当我返回指向我的内存映射文件的指针或我在结构中返回我的文件时,数据在函数范围之外丢失.我的功能应该返回什么
#include <iostream>
#include <fstream>
#include <boost/iostreams/device/mapped_file.hpp>
using namespace std;
using namespace boost::iostreams;
struct data
{
public:
long long timestamp;
double number1;
double number2;
};
int fileSize(ifstream &stream){
stream.seekg(0, ios_base::end);
return stream.tellg();
}
mapped_file_source * getData(const string& fin){
ifstream ifs(fin, ios::binary);
mapped_file_source file;
int numberOfBytes = fileSize(ifs);
file.open(fin, numberOfBytes);
// Check if file was successfully opened
if (file.is_open()) {
return &file;
}
else {
throw - 1;
}
}
int main()
{
mapped_file_source * file = getData("data/bin/2013/6/2/AUD_USD.bin");
struct data* raw …Run Code Online (Sandbox Code Playgroud) 我有一个带有控制器的 Web API,该控制器需要通过内存映射文件与本地工具进行通信。当我尝试使用 OpenExisting 打开此类文件时,出现“找不到文件”错误。
string MMF_In_Name = "MemoryMappedFilename";
MemoryMappedFile MMF_In = MemoryMappedFile.OpenExisting(MMF_In_Name);
Run Code Online (Sandbox Code Playgroud)
我尝试在名称中添加前缀“Global/”,但没有成功。
接下来我尝试从我的控制器启动一个命令行工具。该工具启动,但它得到相同的“文件未找到错误”。当我自己运行该工具时,一切正常。这意味着文件名是正确的。
如何说服 IIS 工作人员让我打开并使用内存映射文件?
我使用的是 Windows Server 2012 和 ISS 8.5。