为什么mmap文件会导致使用比文件大小更多的内存?(Why mmap a file result in using more memory than file's size?)
我正在尝试使用
mmap
并附带以下示例代码:int main() { int fd; char *filename = "/home/manu/file"; struct stat statbuf; int i = 0; char c = *(filename); // Get file descriptor and file length fd = open(filename, O_RDONLY); if (fd == -1) { perror("fopen error"); } if (fstat(fd, &statbuf) < 0) { perror("fstat error"); } printf("File size is %ld\n", statbuf.st_size); // Map the file char* mmapA = (char*) mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (mmapA == MAP_FAILED) { perror("mmap error"); return 1; } // Touch all the mapped pages while (i < statbuf.st_size) { c = mmapA[i]; i++; } c++; // Close file descriptor if (close(fd) == -1) { perror("close"); return 1; } //Unmap file munmap(mmapA, statbuf.st_size); return EXIT_SUCCESS; }
文件大小为137948字节= 134,7千字节。 为了检查程序的内存,我使用top,主要是RES和VIRT列。 我在三个不同的地方寻找这些价值观:
- 就在
mmap
调用之前- 就在
mmap
调用之后- 读完所有映射的内存后,将文件有效地加载到主内存中(页面错误后)
top报告的值是
- VIRT = 1828 RES = 244
- VIRT = 1964 RES = 248
- VIRT = 1964 RES = 508
1964 - 1828 = 136,我猜以千字节为单位,因此完全匹配文件的大小。
但我无法理解508 - 248 = 260的RES差异。为什么它与虚拟内存大小和文件大小不同?
I am experimenting with
mmap
and came with the following sample code:int main() { int fd; char *filename = "/home/manu/file"; struct stat statbuf; int i = 0; char c = *(filename); // Get file descriptor and file length fd = open(filename, O_RDONLY); if (fd == -1) { perror("fopen error"); } if (fstat(fd, &statbuf) < 0) { perror("fstat error"); } printf("File size is %ld\n", statbuf.st_size); // Map the file char* mmapA = (char*) mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (mmapA == MAP_FAILED) { perror("mmap error"); return 1; } // Touch all the mapped pages while (i < statbuf.st_size) { c = mmapA[i]; i++; } c++; // Close file descriptor if (close(fd) == -1) { perror("close"); return 1; } //Unmap file munmap(mmapA, statbuf.st_size); return EXIT_SUCCESS; }
The file size is 137948 bytes = 134,7 kilobytes. To inspect program's memory I am using top, mainly the RES and VIRT columns. I am looking for these values at three different places:
- just before the
mmap
call- just after the
mmap
call- after having read all the mapped memory to have the file's effectively loaded into main memory (after page faults)
The value reported by top are
- VIRT = 1828 RES = 244
- VIRT = 1964 RES = 248
- VIRT = 1964 RES = 508
1964 - 1828 = 136, I guess in kilobytes and thus perfectly match the file's size.
But I can't understand the RES difference of 508 - 248 = 260 .. Why is it different from virtual memory size and file size ?
原文:https://stackoverflow.com/questions/10216433
最满意答案
这是问题的开始:
ResponseError = request.RequestError;
您有一个
Error
对象 - 在该行之后,您的响应和请求都引用同一个对象。 请记住,Error
是一个类,因此Request.RequestError
和Response.ResponseError
的值是引用。然后在此处修改对象:
r.ResponseError.ErrorDescription = "New Response Description";
如果您仍然不完全理解,您可能想阅读我关于参考和值的文章 。
This is the start of the problem:
ResponseError = request.RequestError;
You have a single
Error
object - after that line, your response and request both refer to the same object. Bear in mind thatError
is a class, so the values ofRequest.RequestError
andResponse.ResponseError
are references.You then modify the object here:
r.ResponseError.ErrorDescription = "New Response Description";
If you still don't fully understand, you might want to read my article on references and values.
相关问答
更多-
方法参数C#(Method Parameters C#)[2023-09-07]
你不能 - 至少不使用调试器API(至少是非平凡的)。 该信息无法通过反射获得。 特别是,您正在获取的MethodBase对象可能在每次调用时都是相同的。 (我不认为你编写的方法与你所展示的方法完全一样,我真的希望你不要在这样的循环中调用GetParameters ,但这是一个副问题。) You can't - not without using the debugger API, at least (which is distinctly non-trivial). That information is ... -
传递方法作为参数使用C#(Pass Method as Parameter using C#)[2023-05-08]
您可以使用.net 3.5中的Func委托作为RunTheMethod方法中的参数。 Func委托允许您指定一个采用特定类型的许多参数的方法,并返回特定类型的单个参数。 这是一个应该工作的例子: public class Class1 { public int Method1(string input) { //... do something return 0; } public int Method2(string input) ... -
Ctrl + Shift + 空格会做你想要的。 你可能想查看一个关键绑定的海报 。 Ctrl+Shift+Space will do what you want. You might want to check out a poster of key bindings.
-
改变线 document.getElementById(key).value=y; 至 document.getElementById('key').innerHTML=y; Change the line document.getElementById(key).value=y; to document.getElementById('key').innerHTML=y;
-
winrt磁贴更新错误C#(Error in winrt tile updates C#)[2023-07-29]
XML对我来说似乎很好,但是您正在安排通知刚刚过去的时间。 在构造函数之前添加时间偏移量。 编辑看起来它比这更微妙,我想也许是因为各种时间功能如何相对于UTC工作。 例如, DateTimeOffset time = DateTime.Now.AddMinutes(3); 没问题,但不是: DateTimeOffset time = DateTime.Now; time = time.Add(new TimeSpan(0, 0, 3, 0, 0)); 我在关于预定通知的博客文章中有一些信息可能有所帮助。 ... -
C#方法作为参数(C# method as parameter)[2022-07-12]
最接近的是使用Delegate - 调用者需要选择正确的委托类型。 这正是Control.Invoke使用Delegate而不是特定委托类型的原因。 另外,HackedByChinese建议使用MethodInfo 。 你应该使用哪一个取决于你想要达到的目标 - 每个都在不同的环境中有用。 如果您正在尝试描述方法 ,那么MethodInfo可能是最好的方法。 如果您尝试表示某种类型的可调用操作 (可以采用参数并具有返回值),则委托可能更有用。 如果您告诉我们更多关于您想要实现的目标,我们可以为您提供更多帮助 ... -
这是问题的开始: ResponseError = request.RequestError; 您有一个Error对象 - 在该行之后,您的响应和请求都引用同一个对象。 请记住, Error是一个类,因此Request.RequestError和Response.ResponseError的值是引用。 然后在此处修改对象: r.ResponseError.ErrorDescription = "New Response Description"; 如果您仍然不完全理解,您可能想阅读我关于参考和值的文章 。 ...
-
有很多方法。 最少的代码是将Action传递给您的服务器,例如: Server s = new Server(); s.start(dataFromClient => { // do something with data from client }); 并在HandleConnectionAsync中调用动作,例如: private async void HandleConnectionAsync(TcpClient tcpClient, Action
callback) { ... -
一般来说,如果可能的话,你应该避免使用ref和out。 也就是说,当方法可能需要修改该值时使用ref。 当方法总是应该为该值赋值时使用。 ref和out之间的区别在于,在使用out时,编译器会强制执行规则,您需要在返回之前将某些内容分配给out参数。 在使用ref时,必须先将该值赋给该变量, 然后再将其用作ref参数。 显然,当你正在编写你自己的方法时,上述内容就适用。 如果您需要调用在参数上使用ref或out修饰符声明的方法,则在调用方法时,应在参数之前使用相同的修饰符。 还要记住,C#通过引用传递引用类 ...
-
当然,在您的情况下, BusinessResponse
是一个class ,也称为“引用类型” 。 引用类型(对象) 总是在C#中“通过引用”传递,(类似于良好的C中的指针) 1 。 这意味着无论你如何传递引用,它仍然指的是内存中的一个实例 。 这意味着无论你如何引用它,你总是修改相同的副本。 1 - 这不完全正确。 实际发生的是参考 (变量)是按值传递的。 当函数接收到这个引用时(再次考虑指向托管堆上某个对象的指针),它将引用同一个对象。 但是,参考本身在传入时被复制。 我们使用的另一种变量是“值类型 ...