由OJ提交结果联想到内存页面大小的一些小猜想

来源:互联网 发布:中国气象数据网吧 编辑:程序博客网 时间:2024/05/01 05:24

       今天不知道抽起那条筋,去看了下之前买的二手的盗版的《APUE》。虽然对于Unix/Linux系统来说,我可以说是一概不知,但是看了前几章,感觉Linux和Windows都有不少相似的地方,当然不是指内核那些。好吧,其实我想说的不是这个。

        其实想说的是,今晚提交完之后,看着那个提交结果,尤其是那个内存使用量,突然联想到了些什么。然后去翻一下自己AC过的题目,也是去看那个内存量。发现了一个规律,这些内存使用量均是4K的倍数。从这个4K,又想起上学期看的《操作系统原理》和《Windows核心编程 5th》里面曾经提到过系统使用的页面大小一般为4K或者为8K。于是果断去翻了一下核心编程(Orz,我没有关于操作系统原理的书),于是发现如下一段话:

       “当应用程序预订地址空间中的一块区域时,系统会确保区域的大小正好是系统页面大小的整数倍。页面是一个内存单元,系统通过它来管理内存。与分配粒度相似,页面大小会根据不同的CPU而有所不同。X86和X64系统使用的页面大小为4KB,而IA-64系统使用的页面大小为8KB。如果应用程序试图预订一块大小为10KB的地址空间区域,那么系统会自动将该请求取整到页面大小的整数倍,然后用取整后的大小预订区域。这意味着在X86和X64系统中,系统会预订一块大小为12KB的区域,而在IA-64系统中,系统会预订一块 16KB的区域。”

         如此一来,就可以解释为什么OJ显示的提交结果全部都是4KB的倍数了。因为内存的分配都是以页面大小为分配粒度,所以会取整到4K。

         还有一个现象就是,就算我在程序开了很大的数组,如果我的OJ的测试数据根本用不到那么多空间,OJ显示的提交结果就是实际所用的内存使用了,而不是数组所占的字节大小。如果在这一种情况下,我调用了memset来对数组中所有元素赋值,那么OJ显示的提交结果就是接近我开的数组的大小。那么这种现象又是如何解释呢?

        这又让我想起了核心编程里面提到的一个概念----“调拨”。原文是这样的:“为了使用所预订的地址空间区域,我们还必须物理存储器,并将存储器映射到所预订的区域。这个过程被称为调拨物理存储器。物理存储器始终都以页面为单位来调拨。我们通过调用VirtualAlloc函数来将物理存储器调拨给所预订的区域。当我们调拨物理存储器给区域时,并不需要给整个区域都调拨物理存储器。例如,我们可以预订一块大小为64KB的区域,然后把物理存储器拨给该区域中的第2个页面和第4个页面。当程序不再需要访问所预订区域中已调拨的物理存储器时,应该释放物理存储器,这个过程被称为撤销调拨物理存储器,通过调用VirtualFree函数来完成。”

        不知道那个OJ系统是不是也是用这种方式来计算提交上来的程序内存使用量呢?但是,这里面又有一个问题,我的数组是开在全局作用域的,正确来说在编译的时候就已经确定下来到底需要多少字节的,如果OJ也是按照一般的编译步骤的话,应该也是得到这一个结果。接着我又去看了一下任务管理器这个程序的内存使用,发现这个数据和我计算的、OJ提交结果都不相同,而且差很远的说,这又是为什么呢?

原创粉丝点击