Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

C言語で、作成したファイルが断片化しないようにする方法。(Linux編)

More than 5 years have passed since last update.

creat()などで作成したファイルに、大きなデータを書き込むとファイルの断片化が起こるが、データを書き込む前に領域を確保しておけば、断片化が起こる可能性を減らすことが出来る。

sample.c
#define _GNU_SOURCE

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <linux/falloc.h>

int main(void)
{
 int fd = creat("sample.dat", S_IRUSR | S_IWUSR);

 /* 領域を128MB確保する */
 fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, 1024 * 1024 * 128);

 /* ここにデータを書き込む処理を書く */

 return 0;
}

上記のコードを実行して作成したsample.datに対して、filefragコマンドを実行すると以下のように表示される。

$filefrag -v sample.dat 
Filesystem type is: ef53
File size of sample.dat is 0 (0 blocks, blocksize 4096)
 ext logical physical expected length flags
   0       0  4435968           30720 unwritten,eof
   1   30720  4466688            2048 unwritten,eof
sample.dat: 1 extent found

ファイルサイズは0のままだが、連続した実領域が確保されているのが確認できる。

上記の通り、fallocate()はファイルサイズ(の値)を変更しないので、そこが気になる場合は代わりにposix_fallocate()を使用する。

sample2.c
#define _GNU_SOURCE

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <linux/falloc.h>

int main(void)
{
 int fd = creat("sample2.dat", S_IRUSR | S_IWUSR);

 /* 領域を256MB確保する */
 posix_fallocate(fd, 0, 1024 * 1024 * 256);

 /* ここにデータを書き込む処理を書く */

 return 0;
}

上記のコードを実行して作成したファイルに対して、filefragコマンドを実行すると以下のようになる。

$filefrag -v sample2.dat 
Filesystem type is: ef53
File size of sample2.dat is 268435456 (65536 blocks, blocksize 4096)
 ext logical physical expected length flags
   0       0  4548608           30720 unwritten
   1   30720  4579328           30720 unwritten
   2   61440  4610048            4096 unwritten,eof
sample2.dat: 1 extent found

File sizeが268435456になっている。

ちなみに、fallocate()は本来、ディスクスペースを確実に確保するための関数、つまり、

データをファイルに書き出そうとしたけど、空きが無くて失敗したよ\(^o^)/

という状況を事前に防ぐ為の関数であって、断片化を防ぐためのものでは無い。連続領域が確保されるのはオマケみたいなもん。

他にも、fallocate()実行にかかるコストはほとんど無いとか、確保した領域は0で埋められている事が期待できるので、作成したファイルに対してゼロフィルする必要が無いとか、そういう利点もあったりする。

欠点は、使えるファイルシステムが限られる点。ext4やXFS、btrfsは対応しているが、今でもよく使われていると思われるext3は未対応。

あと、ext4は連続領域を確保する性能が低いので、fallocate()で128MBを超える領域を確保すると断片化しやすい。XFSはその辺は優秀で、1GBを超えても余裕で連続領域を確保できる。

WindowsではSetFilePointer()とSetEndOfFile()を使えば連続領域を確保出来るらしいので、誰かサンプルソース下さい。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away