kvm のソースを読んでたら kvm_kvzalloc() なる関数が出てきた
/* * Avoid using vmalloc for a small buffer. * Should not be used when the size is statically known. */ void *kvm_kvzalloc(unsigned long size) { if (size > PAGE_SIZE) return vzalloc(size); else return kzalloc(size, GFP_KERNEL); }
割り当てたいサイズによって vzalloc() と kzalloc() を使い分ける。 kzalloc() は下記のような感じ
/** * kzalloc - allocate memory. The memory is set to zero. * @size: how many bytes of memory are required. * @flags: the type of memory to allocate (see kmalloc). */ static inline void *kzalloc(size_t size, gfp_t flags) { return kmalloc(size, flags | __GFP_ZERO);
__GFP_ZERO を指定すると 割り当てた領域は 0
で初期化済みで返してくれる。
#define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* Return zeroed page on success */
疑問
ここんところの実装がどうなってるかを追ってみた
といっても memset() しているだけだった。ちょっと面白みがないので下記のような検証を加えた
検証
まずは kzalloc() と kmalloc() したアドレスを dmesg に出すだけのカーネルモジュールを作る
#include <linux/module.h> #include <linux/slab.h> MODULE_AUTHOR("hiroya"); MODULE_DESCRIPTION("kzalloc test"); MODULE_LICENSE("GPL"); void *kz, *km; static int __init kzalloc_init(void) { kz = kzalloc(PAGE_SIZE, GFP_KERNEL); km = kmalloc(PAGE_SIZE, GFP_KERNEL); pr_info("kzalloc: %p kmalloc: %p\n", kz, km); return 0; } static void __exit kzalloc_exit(void) { kfree(kz); kfree(km); } module_init(kzalloc_init); module_exit(kzalloc_exit);
モジュールを insmod すると dmesg に下記のようなログがでる
[ 334.125706] kzalloc: ffff880019f0d000 kmalloc: ffff880019f0f000
このアドレスを使って、メモリの内容を gdb + vmlinx + /proc/kcore でダンプする。ダンプの範囲は PAGE_SIZE = 4KB
$ sudo gdb /usr/lib/debug/lib/modules/3.10.0-327.36.3.el7.x86_64/vmlinux /proc/kcore (gdb) dump mem /tmp/kzalloc 0xffff880019f0d000 0xffff880019f0e000 (gdb) dump mem /tmp/kmalloc 0xffff880019f1d000 0xffff880019f1e000
kzalloc() で割り当てた範囲のダンプは 0 初期化されているのが確認できる
$ hexdump -C /tmp/kzalloc 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00001000
kmalloc() で割り当てた範囲のダンプは ゴミが混じっている。(何のデータかはわからない
$ hexdump -C /tmp/kmalloc 00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000002c0 00 00 00 00 00 00 00 00 67 b0 04 17 00 00 00 80 |........g.......| 000002d0 67 50 69 17 00 00 00 80 67 70 41 17 00 00 00 80 |gPi.....gpA.....| 000002e0 67 f0 68 17 00 00 00 80 00 00 00 00 00 00 00 00 |g.h.............| 000002f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00000710 25 10 94 01 00 00 00 00 00 00 00 00 00 00 00 00 |%...............| 00000720 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00001000