C 当从mmap向下传递偏移量时,mmap调用失败
在linux下: #free -m total used free shared buffers cached Mem: 1995 1460 534 0 68 432 -/+ buffers/cache: 959 1035 Swap: 2055 743 1311 # cat /proc/sys/vm/overcommit_memory 0 #cat /proc/sys/vm/overcommit_ratio 50 #自由-m 缓存的可用共享缓冲区总数 成员:1995 1460534068432 -/+缓冲区/高速缓存:959 1035 掉期:20557431311 #cat/proc/sys/vm/overmit\u内存 0 #cat/proc/sys/vm/OVERMIT_比率 50 测试代码1:C 当从mmap向下传递偏移量时,mmap调用失败,c,linux,offset,mmap,C,Linux,Offset,Mmap,在linux下: #free -m total used free shared buffers cached Mem: 1995 1460 534 0 68 432 -/+ buffers/cache: 959 1035 Swap: 2055 743 1311 #
#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);
}
#定义每页大小4096
#定义MMAP(fd,偏移量)MMAP(空,每页大小,保护读取,保护写入,映射共享,映射无保留,fd,偏移量)
int main(){
int j=0;
int fd=打开(“数据tmp”,O_RDWR);
对于(int i=131071;i>=0;i--){
++j;
void*r=MMAP(fd,i*4096);
如果(r==映射_失败){
printf(“%d,%m\n”,j);
打破
}
}
cout这是我的猜测。我猜第二个程序只是扩展了一个描述单个映射的内部数据结构以包含更多的页面。第一个程序可以做到这一点,但它必须向后扩展,我打赌合并映射的特例代码甚至没有检查这一点
它停在65513这一事实很有启发性。共享库等将使用一些映射,因此可用的映射将少于65536个。而65536是许多内核用户用于数据结构的大小
我建议查看/proc//maps
并查看程序睡眠时每种情况下列出的映射数。为了方便起见,您可能希望在打印“完成”消息时打印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);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义每页大小4096
#定义MMAP(fd,偏移量)MMAP(空,每页大小,保护读取,保护写入,映射共享,映射无保留,fd,偏移量)
int main()
{
使用::std::cout;
使用::std::endl;
int j=0;
int fd=打开(“数据tmp”,O_RDWR);
char catcmd[]=“cat/proc/99999/maps_padding”;
对于(int i=131071;i>=0;i-=2){
++j;
void*r=MMAP(fd,i*4096);
如果(r==映射_失败){
cout这是我的猜测。我猜第二个程序只是扩展了一个描述单个映射的内部数据结构以包含更多的页面。第一个程序可以做到这一点,但它必须向后扩展,我打赌合并映射的特例代码甚至没有检查这一点
它停在65513这一事实很有启发性。共享库等将使用一些映射,因此可用的映射将少于65536个。而65536是许多内核用户用于数据结构的大小
我建议查看/proc//maps
并查看程序睡眠时每种情况下列出的映射数。为了方便起见,您可能希望在打印“完成”消息时打印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);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义每页大小4096
#定义MMAP(fd,偏移量)MMAP(空,每页大小,保护读取,保护写入,映射共享,映射无保留,fd,偏移量)
int main()
{
使用::std::cout;
使用::std::endl;
int j=0;
int fd=打开(“数据tmp”,O_RDWR);
char catcmd[]=“cat/proc/99999/maps_padding”;
对于(int i=131071;i>=0;i-=2){
++j;
void*r=MMAP(fd,i*4096);
如果(r==映射_失败){
cout如果以“对不起,代码已重新格式化”启动第二个程序,会发生什么情况。在两种情况下:循环变量从大到小的变化,以及从小到大的变化,mmap行为不同。当循环变量是从大到小的变化,且计数器“j”达到65513时,“mmap”调用失败(无法分配内存),相反,它确实有效。我无法重现问题。系统上uname-a
的输出是什么?如果用“启动第二个程序,会发生什么?”抱歉,代码已重新格式化。在两种情况下:循环变量从大到小的更改,以及从小到大的更改,mmap行为不同。当循环变量是从大到小的更改,并且计数器“j”达到65513时,“mmap”调用失败(无法分配内存),相反,它确实有效。我无法重现这个问题。您的系统上的uname-a
的输出是什么?看看这个关于映射限制的线程:@hydroneaud-谢谢您的链接。这很有趣。我想我会将它末尾的一些信息复制到我的答案中。@hydroneaud-谢谢您的答案,我会的下面介绍这些方法来解决我的问题。@user619600-如果答案看起来非常完整且有用,那么接受对你帮助最大的答案被认为是礼貌的。看看这个关于映射限制的帖子:@hydroneaud-谢谢你的链接。这很有趣。我想我会把它末尾的一些信息复制到我的answ中呃。@Hydroneaud-谢谢你的回答,我会按照这些方法来解决我的问题。@user619600-如果答案看起来总体上是完整和有用的,那么接受对你帮助最大的答案被认为是礼貌的。