QEMU源码全解析 —— 内存虚拟化(24)

接前一篇文章: QEMU源码全解析 —— 内存虚拟化(23)

本文内容参考:

《趣谈 Linux操作系统 》 —— 刘超, 极客时间

QEMU /KVM源码解析与应用》 —— 李强,机械工业出版社

QEMU内存管理模型

浅谈QEMU Memory Region 与 Address Space

【QEMU系统分析之实例篇(七)】-CSDN博客

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函数余下代码的解析,请看下回。