接前一篇文章: QEMU源码全解析 —— 内存虚拟化(23)
本文内容参考:
《 QEMU /KVM源码解析与应用》 —— 李强,机械工业出版社
浅谈QEMU Memory Region 与 Address Space
QEMU内存分析(一):内存虚拟化关键结构体 - Edver - 博客园
特此致谢!
2. QEMU虚拟机内存初始化
上一回在讲解address_space_init函数中调用的address_space_update_topology函数时,讲到了flatviews_init函数,没有讲完,本回接着讲解该函数其余内容。为了便于理解和回顾,再次贴出flatviews_init函数代码,在softmmu/memory.c中,如下:
static void flatviews_init(void)
{
static FlatView *empty_view;
if (flat_views) {
return;
}
flat_views = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) flatview_unref);
if (!empty_view) {
empty_view = generate_memory_topology(NULL);
/* We keep it alive forever in the global variable. */
flatview_ref(empty_view);
} else {
g_hash_table_replace(flat_views, NULL, empty_view);
flatview_ref(empty_view);
}
}
上一回讲到,flat_views是一个静态全局变量,在同文件(softmmu/memory.c)中,定义如下:
static GHashTable *flat_views;
如果flat_views不是首次创建(之前已经创建过),则直接返回。由于这里是首次创建,因此回往下进行。
接下来就是调用g_hash_table_new_full函数,代码片段如下:
flat_views = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) flatview_unref);
这部分内容涉及到了glib库中的哈希表GHashTable的相关内容。需要进行知识补强。
知识补强 —— g_hash_table
参考以下文章:
glib g_hash_table_new g_hash_table_new_full - lydstory - 博客园
【glibc】glib库hash表GHashTable介绍 - opensmarty - 博客园
hash表是一种提供key-value访问的数据结构,通过指定的key值可以快速地访问到与它相关联的value值。hash表的一种典型用法就是字典,通过单词的首字母能够快速地找到单词。关于hash表的详细介绍请查阅数据结构的相关书籍,这里只介绍glib库中hash表的基本用法。
要使用一个hash表首先必须创建它,glib库里有两个函数可以用于创建hash表,分别是g_hash_table_new()和g_hash_table_new_full(),它们的原型如下:
GHashTable * g_hash_table_new(GHashFunc hash_func, GEqualFunc key_equal_func);
GHashTable * g_hash_table_new_full(GHashFunc hash_func,
GEqualFunc key_equal_func,
GDestroyNotify key_destroy_func,
GDestroyNotify value_destroy_func);
其中:
- GHashFunc hash_func —— hash_func是一个函数,它为key创建一个hash值。
- GEqualFunc key_equal_func —— key_equal_func用于比较两个key是否相等。
- GDestroyNotify key_destroy_func —— 当你从hash表里删除、销毁一个条目时,glib库会自动调用它释放key所占用的内存空间,这对于key是动态分配内存的hash表来说非常有用。
- GDestroyNotify value_destroy_func —— value_destroy_func的作用与key_destroy_func相似,只是它释放的是value占用的内存空间。
回到代码中,
flat_views = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) flatview_unref);
这段代码的意思就是使用g_direct_hash函数创建一个哈希表,并设置用来比较key的函数为g_direct_equal(),不设置删除key的函数,设置删除value的函数为flatview_unref()。将函数返回的句柄保存在flat_views中。
flatviews_init函数余下代码的解析,请看下回。