由于分段错误改变了巨大的页面分配的大小时进行初始化()函数 [英] segmentation fault due to initialize() function when changing the size of the huge page allocation

查看:259
本文介绍了由于分段错误改变了巨大的页面分配的大小时进行初始化()函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到段错误在我的计划时,我与我要和巨大的页面,也就是分配内存的大小,玩的时候我定义长度= 4 * 1024,有赛格故障。当我定义4 * 1024 * 1024,没有赛格故障。这什么的根本原因?

code如下:

 的#define _POSIX_C_SOURCE 199309
#定义_GNU_SOURCE
#包括LT&;&sched.h中GT;
#包括LT&;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / mman.h>
#包括LT&;&fcntl.h GT;
#包括LT&;&time.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&errno.h中GT;#定义保护(PROT_READ | PROT_WRITE)
的#define长度(4 * 1024)
//#定义长度(4 * 1024 * 1024)
#定义LINE_SIZE 64
#定义ASSOC 16
的#define CACHE_SIZE(4 * 1024 * 1024)
#定义WAY_SIZE(CACHE_SIZE / ASSOC)的#ifndef MAP_HUGETLB
#定义MAP_HUGETLB 0x40000
#万一#定义ADDR(无效*)(0x0UL)
#定义标志(MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)INT主(INT ARGC,CHAR *的argv []){
...
  //如使用巨大的页面LLC分配一个缓冲器具有相同大小
  BUF = MMAP(ADDR,长度,保护,旗帜,0,0);
  如果(BUF == MAP_FAILED){
    PERROR(MMAP);
    出口(1);
  }
  set_S =的atoi(ARGV [1]);
  set_M =与atoi(argv的[2]);
  的printf(测试0 \\ n);
  初始化(set_S);
  的printf(测试1 \\ n);
  初始化(set_M);
  的printf(测试2 \\ n);
  head_S =安培; BUF [set_S * LINE_SIZE]。
  的printf(测试3 \\ n);
  head_M =安培; BUF [set_M * LINE_SIZE]。...
}

需要注意的是在我的电脑默认启用没有庞大的页面,所以我把它作为根:

 回声20 GT;的/ proc / SYS / VM / nr_hugepages

这是在/ proc / meminfo中我打开巨大的页面后,页面庞大的相关信息:

  HugePages_Total:20
HugePages_Free:20
HugePages_Rsvd:0
HugePages_Surp:0
Hugepagesize:2048 KB

程序输出:

  $。/ a.out的1 1
测试0
分段错误(核心转储)

$的uname输出:

  Linux的mymachine上3.13.0-43泛型#72 Ubuntu的SMP周一12月8日19时35分06秒UTC 2014年的x86_64 x86_64的x86_64的GNU / Linux的

编辑1:添加初始化函数:

  void初始化(INT组){
  INT J,K;
  焦炭** ptr1的,** PTR2;
  字符* tmp目录;  //重新初始化大小大小的指针数组
  //执行Sattolo的随机循环置换
  为(J = 0; J< ASSOC; J ++){
    ptr1的=(字符**)及BUF [设置* LINE_SIZE + J * WAY_SIZE]。
    * ptr1的=(字符*)ptr1的;
  }  //置换每组
  为(J = ASSOC-1,J> = 1;的J - ){
    K =兰特()%焦耳;
    ptr1的=(字符**)及BUF [设置* LINE_SIZE + J * WAY_SIZE]。
    PTR2 =(字符**)及BUF [设置* LINE_SIZE + K * WAY_SIZE]。
    TMP = * ptr1的;
    * ptr1的= * PTR2;
    * PTR2 = tmp目录;
  }
}


解决方案

当访问设置* LINE_SIZE +(ASSOC-1)* WAY_SIZE =设置* 64 + CACHE_SIZE - WAY_SIZE =设置* 64 + 4 * 1024 * 1024 - WAY_SIZE 比MMAP长度长度= 4 * 1024 的环路初始化您正在访问的内存越界。这就是为什么你有段故障时定义长度的原因= 4 * 1024。

I encounter segmentation fault in my program when I play with the size of the memory that I want to allocate with huge page, i.e., when I define LENGTH = 4*1024, there is seg fault. When I define 4*1024*1024, there is no seg fault. What is the root cause of this?

Code below:

#define _POSIX_C_SOURCE 199309
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <time.h>
#include <string.h>
#include <errno.h>

#define PROTECTION (PROT_READ | PROT_WRITE)
#define LENGTH (4*1024)
//#define LENGTH (4*1024*1024)
#define LINE_SIZE 64
#define ASSOC 16
#define CACHE_SIZE (4*1024*1024)
#define WAY_SIZE (CACHE_SIZE/ASSOC)

#ifndef MAP_HUGETLB
#define MAP_HUGETLB 0x40000
#endif

#define ADDR (void *) (0x0UL)
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)

int main (int argc, char *argv[]){
...
  // allocate a buffer with the same size as the LLC using huge pages
  buf = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
  if (buf == MAP_FAILED) {
    perror("mmap");
    exit(1);
  }
  set_S = atoi(argv[1]);
  set_M = atoi(argv[2]);
  printf("test 0\n");
  initialize(set_S);
  printf("test 1\n");
  initialize(set_M);
  printf("test 2\n");
  head_S = &buf[set_S*LINE_SIZE];
  printf("test 3\n");
  head_M = &buf[set_M*LINE_SIZE];

...
}

Note that there is no huge page on enabled by default in my computer, so I turned it on as root:

echo 20 > /proc/sys/vm/nr_hugepages

This is the huge page related info in /proc/meminfo after I turn on huge page:

HugePages_Total:      20
HugePages_Free:       20
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

Program output:

$./a.out 1 1
test 0
Segmentation fault (core dumped)

$uname output:

Linux mymachine 3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

EDIT 1: Add the initialize function:

void initialize(int set){
  int j, k;
  char ** ptr1, ** ptr2;
  char * tmp;

  // re-initialize pointer array of size "size"
  // implementation of Sattolo's random cyclic permutation
  for (j=0; j<ASSOC; j++){
    ptr1 = (char **)&buf[set*LINE_SIZE+j*WAY_SIZE];
    *ptr1 = (char*)ptr1;
  }

  // permute each set
  for (j=ASSOC-1; j>=1; j--){
    k = rand()%j;
    ptr1 = (char **)&buf[set*LINE_SIZE+j*WAY_SIZE];
    ptr2 = (char **)&buf[set*LINE_SIZE+k*WAY_SIZE];
    tmp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = tmp;
  }
}

解决方案

When accessing set*LINE_SIZE+(ASSOC-1)*WAY_SIZE = set*64 + CACHE_SIZE - WAY_SIZE = set*64 + 4*1024*1024 - WAY_SIZE which is bigger than mmap length LENGTH = 4*1024 in the loop of initialize , you are accessing memory out of bound. That's the reason why you got segment fault when define LENGTH = 4*1024.

这篇关于由于分段错误改变了巨大的页面分配的大小时进行初始化()函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆