トップ «前の日記(2011年07月12日) 最新 次の日記(2011年08月29日)» 編集
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|10|12|
2009|02|03|06|07|10|11|12|
2010|01|02|03|04|07|09|10|11|12|
2011|01|03|04|05|06|07|08|10|
2012|01|06|08|09|10|12|
2013|01|02|03|04|07|09|11|12|
2014|01|03|04|05|06|09|
2015|04|
2016|01|08|
ここは旧えびめもです。えびめも2に移行します(2016/12/1)

2011年08月04日

qemuが確保するメモリ量について

qemuのlinuxユーザモードエミュレーションは便利である。しかしqemu上で確保するメモリ量は通常1.5Gバイトほどのようである。次のコードで実験した。
#include 
 
#define SIZE_1M (1024*1024)
#define LIMIT 4096
 
int main(){
        int *p;
        int i;
        for(i=0; i < LIMIT; i++){
                p=malloc(SIZE_1M);
                if(p==NULL){
                        printf("NIL\n");
                        perror("");
                        return 1;
                }
                memset(p,i,SIZE_1M);
                printf("%d Mbyte\n",i);
        }
}
ビルド&ラン
 $ sh4-linux-gnu-gcc malloc_test.c -static
 $ qemu-sh4 ./a.out
 ざっくりと略
 1526 Mbyte
 1527 Mbyte
 1528 Mbyte
 1529 Mbyte
 qemu: uncaught target signal 11 (Segmentation fault) - core dumped
 Segmentation fault
なわけで およそ1.5Gで死ぬ。 大規模パッケージのリンク工程などで1.5Gではメモリが足りないことがある。qemuのドキュメントを見ると -R オプションで回避できるようだ。
 $ qemu-sh4 -R 4G ./a.out      (4Gをリザーブする)
 4092 Mbyte
 4093 Mbyte 
 4094 Mbyte
 4095 Mbyte
qemuのソースコードを見ると、事前に -R オプションで指定した reserved_va サイズだけ mmap()するようだ。

毎度毎度 -R 4G するのも大変だし(vmaを確保するのに余計な時間がかかりそうなので)環境変数 QEMU_4G=1 を付加した時に -R 4G と同じ動作をするパッチを作った。
 --- linux-user/main.c-orig      2011-08-04 11:45:43.000000000 +0000
 +++ linux-user/main.c   2011-08-04 11:45:14.000000000 +0000
 @@ -2941,40 +2941,44 @@
  #endif
      }
      cpu_exec_init_all(0);
      /* NOTE: we need to init the CPU at this stage to get
         qemu_host_page_size */
      env = cpu_init(cpu_model);
      if (!env) {
          fprintf(stderr, "Unable to find CPU definition\n");
          exit(1);
      }
  #if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
      cpu_reset(env);
  #endif
 
      thread_env = env;
 
      if (getenv("QEMU_STRACE")) {
          do_strace = 1;
      }
 
 +    if (getenv("QEMU_4G")){
 +       reserved_va = 0xffffffff;
 +    }
 +
      target_environ = envlist_to_environ(envlist, NULL);
      envlist_free(envlist);
使ってみる
 qemu-sh4 を使って動いている sh4 debian の chroot 内で
 $ export QEMU_4G=1     指定
 $ ./a.out
 ざっくり略
 4092 Mbyte
 4093 Mbyte
 4094 Mbyte
 4095 Mbyte
 $ export -n QEMU_4G    解除
 
ばっちり