2017-06-02 10 views
5

巨大なファイルをゼロにする必要があります。私はこのステップを巨大なファイルサイズ(何百ギガバイトもの)を伴うfopen => ftruncate => fclose => mmap => (...work...) => munmapを作り出しています。システムがファイルバイトをゼロにしようとしている間、アプリケーションは終了時に数分間停止します - ftruncateのためIMHO。ゼロ化せずにディスクにファイルを割り当てます。

ftruncate(ofd, 0); 

#ifdef HAVE_FALLOCATE 

    int ret = fallocate(ofd, 0, 0, cache_size); 
    if (ret == -1) { 
     printf("Failed to expand file to size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno)); 
     exit(-1); 
    } 

#elif defined(HAVE_POSIX_FALLOCATE) 

    int ret = posix_fallocate(ofd, 0, cache_size); 
    if (ret == -1) { 
     printf("Failed to expand file to size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno)); 
     exit(-1); 
    } 

#elif defined(__APPLE__) 

    fstore_t store = {F_ALLOCATECONTIG, F_PEOFPOSMODE, 0, cache_size, 0}; 
    int ret = fcntl(ofd, F_PREALLOCATE, &store); 
    if (ret == -1) { 
     store.fst_flags = F_ALLOCATEALL; 
     ret = fcntl(ofd, F_PREALLOCATE, &store); 
    } 
    if (ret == -1) { // read fcntl docs - must test against -1 
     printf("Failed to expand file to size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno)); 
     exit(-1); 
    } 
    struct stat sb; 
    ret = fstat(ofd, &sb); 
    if (ret != 0) { 
     printf("Failed to write to file to establish the size.\n"); 
     exit(-1); 
    } 
    //ftruncate(ofd, cache_size); <-- [1] 

#endif 

コメント行[1]とは動作しないようです。しかし、この行のコメントを外して、私が避けようとしているファイルのゼロ調整を生成します。私は本当に書く前に汚いファイルの内容を気にしません。私はアプリの終了時にハングアップしないようにしたい。

SOLUTION:

@torfoさんanswerによると、この数行ですべての私のApple関連のコードを置き換える:

unsigned long long result_size = cache_size; 
int ret = fcntl(ofd, F_SETSIZE, &result_size); 
if(ret == -1) { 
    printf("Failed set size %llu (errno %d - %s).\n", cache_size, errno, strerror(errno)); 
    exit(-1); 
} 

しかし、唯一のスーパーユーザのために働きます!

+1

** **( 'ftruncate()'もスパースファイルを作成する必要がありますので、あなたのOS /ファイルシステムはスパースファイルをサポートしていないようです) –

+0

コンテンツをゼロにしないで巨大なファイルを作成する必要がある場合あなたがする他のことをすることなく 'ftruncate'するだけです。あなたのファイルシステムがそれをサポートしている場合、それはスパースファイルを作成します。 'fallocate'と他の呼び出しは逆を行い、ディスクブロックをあらかじめ割り当ててゼロにします。スパースファイルに書き込むときにディスク領域が不足する危険性がありますが、時間を無駄にすることはありません。 – Art

+0

'Ctrl + C 'で終了すると' ftruncate'の@Artアプリが数分間停止します。 – k06a

答えて

5

これは明らかにMacOS Xです。

あなたがしてftruncate呼び出しを置き換えるために試すことができます

fcntl(ofd, F_SETSIZE, &size); 

(ノートではroot権限を必要とし、それが以前にあった古いファイルの内容へのアクセスを提供する可能性があるため、セキュリティホールを作成することがありますので、で処理しなければなりませんあなたが気にしない "汚いファイルの内容"は、実際に彼が一週間前に削除したユーザーの銀行口座のパスワードかもしれません...)

MacOS Xはスパースファイルを本当にサポートしていません。それらを維持するが、そのファイルシステムドライバはできるだけ早く穴を埋めるために非常に熱心である。

+0

ありがとう! 'fcntl(ofd、F_SETSIZE、&result_size);'はチャームのように機能します! – k06a

+1

@ k06aあなたは*私のセキュリティ上の懸念を読んだ? – tofro

+0

このユースケースのセキュリティ上の問題はありません。これはHDDマイニングのプロット世代です:https://github.com/r-majere/mjminer/pull/3 – k06a