この記事はLinux Advent Calendar 2017の22日目の記事です。 カーネルのコードを書いていてサイズを表示したい時にstring_get_size()を使うとお手軽に2進接頭辞(KiBとか)とSI接頭辞(KBとか)を使ったサイズの文字列を作ることができます。
関数のプロトタイプはこうです。
void string_get_size(u64 size, u64 blk_size, enum string_size_units units, char *buf, int len);
sizeとblk_sizeは使い分けが有ります。バイト数を扱いたい場合はsizeにバイト数、blk_sizeには1を指定します。ブロックデバイスやページなどを扱う場合などはそのサイズをblk_sizeに指定して、それがいくつあるかをsizeで指定します。
たとえば、1024という数字を2進接頭辞にするならsizeには1024、blk_sizeは1をセットします。1ページのサイズが4096バイトで1ページのバイト数を2進接頭辞にするならsizeは1、blk_sizeは4096という感じです。 unitsは2進接頭辞かSI接頭辞を指定します。bufに渡した変数に結果が入ります。lenはbufで利用可能なバイト数ですね。
こんな感じで使えます。
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> #include <linux/kernel.h> #include <linux/string_helpers.h> MODULE_DESCRIPTION("size test"); MODULE_AUTHOR("masami256"); MODULE_LICENSE("GPL"); struct size_test_data { u64 size; u64 blk_size; int unit; }; static struct size_test_data data[] = { { .size = 1024, .blk_size = 1, .unit = STRING_UNITS_2, }, { .size = 1024, .blk_size = 1, .unit = STRING_UNITS_10, }, { .size = 1, .blk_size = 4096, .unit = STRING_UNITS_2, }, { .size = 1, .blk_size = 4096, .unit = STRING_UNITS_10, } }; static int size_test_init(void) { int i; for (i = 0; i < sizeof(data) / sizeof(data[0]); i++) { char buf[16] = { 0 }; struct size_test_data tmp = data[i]; string_get_size(tmp.size, tmp.blk_size, tmp.unit, buf, sizeof(buf) - 1); pr_info("size:%lld, blk_size: %lld, unit:%d, %s\n", tmp.size, tmp.blk_size, tmp.unit, buf); } return 0; } static void size_test_cleanup(void) { pr_info("%s bye\n", __func__); } module_init(size_test_init); module_exit(size_test_cleanup);
実行するとこう表示されます。
[ 1402.100472] size_test: size:1024, blk_size: 1, unit:1, 1.00 KiB [ 1402.100474] size_test: size:1024, blk_size: 1, unit:0, 1.02 kB [ 1402.100474] size_test: size:1, blk_size: 4096, unit:1, 4.00 KiB [ 1402.100475] size_test: size:1, blk_size: 4096, unit:0, 4.10 kB
地味に便利ですね( ´ー`)フゥー...
ふつうのLinuxプログラミング 第2版 Linuxの仕組みから学べるgccプログラミングの王道
- 作者: 青木峰郎
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2017/09/22
- メディア: 単行本
- この商品を含むブログを見る