gpt4 book ai didi

c - 当 offset 递减传递给 mmap 时,mmap 调用失败

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:42:19 29 4
gpt4 key购买 nike

在 Linux 下:

#free -m             total       used       free     shared    buffers     cachedMem:          1995       1460        534          0         68        432-/+ buffers/cache:        959       1035Swap:         2055        743       1311# cat /proc/sys/vm/overcommit_memory0#cat /proc/sys/vm/overcommit_ratio50

test code 1:

#define PER_PAGE_SIZE 4096
#define MMAP(fd,offset) mmap (NULL,PER_PAGE_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_NORESERVE,fd,offset)


int main(){
int j = 0;
int fd = open("dat.tmp",O_RDWR);
for(int i = 131071 ; i >= 0; i--){
++j;
void* r = MMAP(fd,i*4096);
if(r == MAP_FAILED){
printf("%d,%m\n",j);
break;
}
}
cout << "done " << j << endl;
sleep(5);
}
##############error  message :# ./a.out 65513,Cannot allocate memorydone 65513...#################

test code 2:

#define PER_PAGE_SIZE 4096
#define MMAP(fd,offset) mmap (NULL,PER_PAGE_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_NORESERVE,fd,offset)

int main(){
int j = 0;
int fd = open("dat.tmp",O_RDWR);
for(int i = 0 ; i <= 131071; i++){
++j;
void* r = MMAP(fd,i*4096);
if(r == MAP_FAILED){
printf("%d,%m\n",j);
break;
}
}
cout << "done " << j << endl;
sleep(5);
}

这是有效的,那么,为什么????????

最佳答案

这是我的猜测。我猜第二个程序只是扩展了描述单个映射的内部数据结构以包含更多页面。第一个可以做到这一点,但它必须向后扩展,我敢打赌用于合并映射的特殊情况代码甚至不会检查这一点。

它在 65513 处停止这一事实非常具有启发性。将有一些映射用于共享库等,因此可用的映射少于 65536 个。 65536 是许多内核人员会用于数据结构的那种大小。

我建议查看 /proc/<pid>/maps并在程序休眠时查看每种情况下列出了多少张 map 。为此,您可能需要打印出 getpid() 的结果。当您打印出“完成”消息时。

我无法直接复制你的问题,所以我的系统似乎已经正确处理了相反的情况。 uname -a 的输出在我的系统上是这样的:

Linux a_hostname.somewhere 2.6.35.11-83.fc14.x86_64 #1 SMP Mon Feb 7 07:06:44 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux

但是这个程序确实复制了你的问题:

#include <iostream>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#define PER_PAGE_SIZE 4096
#define MMAP(fd,offset) mmap (NULL,PER_PAGE_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_NORESERVE,fd,offset)

int main()
{
using ::std::cout;
using ::std::endl;
int j = 0;
int fd = open("dat.tmp",O_RDWR);
char catcmd[] = "cat /proc/99999/maps_padding";
for(int i = 131071 ; i >= 0; i-=2){
++j;
void* r = MMAP(fd,i*4096);
if(r == MAP_FAILED){
cout << j << ", " << strerror(errno) << '\n';
break;
}
}
::std::snprintf(catcmd, sizeof(catcmd), "cat /proc/%d/maps", getpid());
cout.flush();
::std::system(catcmd);
cout << "done " << j << endl;
sleep(5);
}

如你所见,如果你在向后跳过2,问题仍然存在。和 cat /proc/<pid>/maps 的输出从调用 system表明确实有数千张单独的 map 。

如果我停止跳过 2 并简单地向后移动,我最终会得到 2 张 map ,一张较大,另一张不太大。如果可以,内核会将相邻的映射合并为一个映射。

作为进一步证实您的问题与我描述的一样的证据,有这个 nice discussion of /proc/sys/vm/max_map_count .设置该变量允许您更改 map 的数量,默认设置为 65530。

关于c - 当 offset 递减传递给 mmap 时,mmap 调用失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5016588/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com