代码版本qemu1.5,只看linux下使用kvm加速的,guest为x86的。
vl.c:main
atexit(qemu_run_exit_notifiers);
vl.c,注册atexit函数,遍历exit_notifiers,执行每一个node中的notify函数
static void qemu_run_exit_notifiers(void)
{
notifier_list_notify(&exit_notifiers, NULL);
}
void notifier_list_notify(NotifierList *list, void *data)
{
Notifier *notifier, *next;
QLIST_FOREACH_SAFE(notifier, &list->notifiers, node, next) {
notifier->notify(notifier, data);
}
}
typedef struct NotifierList
{
QLIST_HEAD(, Notifier) notifiers;
} NotifierList;
struct Notifier
{
void (*notify)(Notifier *notifier, void *data);
QLIST_ENTRY(Notifier) node;
};
exit_notifiers 哪里来的呢:
static NotifierList exit_notifiers =
NOTIFIER_LIST_INITIALIZER(exit_notifiers);
#define NOTIFIER_LIST_INITIALIZER(head) \
{ QLIST_HEAD_INITIALIZER((head).notifiers) }
void qemu_add_exit_notifier(Notifier *notify)
{
notifier_list_add(&exit_notifiers, notify);
}
error_set_progname(argv[0]);
Qemu-error.c,设置progname为basename:
/*
* Set the program name for error_print_loc().
*/
void error_set_progname(const char *argv0)
{
const char *p = strrchr(argv0, '/');
progname = p ? p + 1 : argv0;
}
g_mem_set_vtable(&mem_trace);
g_mem_set_vtable(&mem_trace);
if (!g_thread_supported()) {
#if !GLIB_CHECK_VERSION(2, 31, 0)
g_thread_init(NULL);
#else
fprintf(stderr, "glib threading failed to initialize.\n");
exit(1);
#endif
}
g_mem_set_vtable用于hook malloc和free,已废弃:https://developer.gnome.org/glib/stable/glib-Memory-Allocation.html
g_thread_init也不需要了:The GLib threading system used to be initialized with g_thread_init(). This is no longer necessary. Since version 2.32, the GLib threading system is automatically initialized at the start of your program, and all thread-creation functions and synchronization primitives are available right away.
https://developer.gnome.org/glib/stable/glib-Threads.html#g-mutex-init
module_call_init(MODULE_INIT_QOM);
参看《qemu QOM(qemu object model)和设备模拟》
runstate_init();
从一个运行状态是否可以切换到另一个运行状态
static void runstate_init(void)
{
const RunStateTransition *p;
memset(&runstate_valid_transitions, 0, sizeof(runstate_valid_transitions));
for (p = &runstate_transitions_def[0]; p->from != RUN_STATE_MAX; p++) {
runstate_valid_transitions[p->from][p->to] = true;
}
}
static bool runstate_valid_transitions[RUN_STATE_MAX][RUN_STATE_MAX];
static const RunStateTransition runstate_transitions_def[] = {
/* from -> to */
{ RUN_STATE_DEBUG, RUN_STATE_RUNNING },
{ RUN_STATE_INMIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_INMIGRATE, RUN_STATE_PAUSED },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_PAUSED },
{ RUN_STATE_INTERNAL_ERROR, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_IO_ERROR, RUN_STATE_RUNNING },
{ RUN_STATE_IO_ERROR, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_PAUSED, RUN_STATE_RUNNING },
{ RUN_STATE_PAUSED, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_POSTMIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_POSTMIGRATE, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_PRELAUNCH, RUN_STATE_RUNNING },
{ RUN_STATE_PRELAUNCH, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_PRELAUNCH, RUN_STATE_INMIGRATE },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_RUNNING },
{ RUN_STATE_FINISH_MIGRATE, RUN_STATE_POSTMIGRATE },
{ RUN_STATE_RESTORE_VM, RUN_STATE_RUNNING },
{ RUN_STATE_RUNNING, RUN_STATE_DEBUG },
{ RUN_STATE_RUNNING, RUN_STATE_INTERNAL_ERROR },
{ RUN_STATE_RUNNING, RUN_STATE_IO_ERROR },
{ RUN_STATE_RUNNING, RUN_STATE_PAUSED },
{ RUN_STATE_RUNNING, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_RUNNING, RUN_STATE_RESTORE_VM },
{ RUN_STATE_RUNNING, RUN_STATE_SAVE_VM },
{ RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN },
{ RUN_STATE_RUNNING, RUN_STATE_WATCHDOG },
{ RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED },
{ RUN_STATE_SAVE_VM, RUN_STATE_RUNNING },
{ RUN_STATE_SHUTDOWN, RUN_STATE_PAUSED },
{ RUN_STATE_SHUTDOWN, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_DEBUG, RUN_STATE_SUSPENDED },
{ RUN_STATE_RUNNING, RUN_STATE_SUSPENDED },
{ RUN_STATE_SUSPENDED, RUN_STATE_RUNNING },
{ RUN_STATE_SUSPENDED, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_WATCHDOG, RUN_STATE_RUNNING },
{ RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED },
{ RUN_STATE_GUEST_PANICKED, RUN_STATE_FINISH_MIGRATE },
{ RUN_STATE_MAX, RUN_STATE_MAX },
};
init_clocks();
rtc_clock = host_clock;
void init_clocks(void)
{
if (!rt_clock) {
rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
vm_clock = qemu_new_clock(QEMU_CLOCK_VIRTUAL);
host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
}
}
static QEMUClock *qemu_new_clock(int type)
{
QEMUClock *clock;
clock = g_malloc0(sizeof(QEMUC