目录
- qemu源码解析【06】qemu启动初始化流程
- 2.4 (书接上文)处理解析出来的参数结果
- 2.5 初始化main loop
- 2.6 杂项
- 2.7 创建machine
- 2.7.1 new一个machine类型出来
- 2.7.2 设置memory page size
qemu源码解析【06】qemu启动初始化流程
2.4 (书接上文)处理解析出来的参数结果
// 验证参数正确性,看起来是linux启动内核相关的参数,我不做linux所以不太熟qemu_validate_options(machine_opts_dict);// smp,cpus这类参数qemu_process_sugar_options();// 影响全局的一些参数,提前处理qemu_process_early_options();// 处理帮助命令qemu_process_help_options();// daemonize进程相关qemu_maybe_daemonize(pid_file);// 初始化日志文件trace_init_file();
2.5 初始化main loop
- qemu_init_main_loop()函数位于util/main-loop.c文件中,主要是注册aio相关配置,这又是一个大的概念,后面单开一篇娓娓道来:
int qemu_init_main_loop(Error **errp)
{int ret;GSource *src;init_clocks(qemu_timer_notify_cb);ret = qemu_signal_init(errp);if (ret) {return ret;}qemu_aio_context = aio_context_new(errp);if (!qemu_aio_context) {return -EMFILE;}qemu_set_current_aio_context(qemu_aio_context);qemu_notify_bh = qemu_bh_new(notify_event_cb, NULL);gpollfds = g_array_new(FALSE, FALSE, sizeof(GPollFD));src = aio_get_g_source(qemu_aio_context);g_source_set_name(src, "aio-context");g_source_attach(src, NULL);g_source_unref(src);src = iohandler_get_g_source();g_source_set_name(src, "io-handler");g_source_attach(src, NULL);g_source_unref(src);return 0;
}
2.6 杂项
// 初始化定时器cpu_timers_init();user_register_global_props();replay_configure(icount_opts);// 配置rtc,real time clock,具体实现位于/system/rtc.c中// 可以选用host系统时钟,或者虚拟时钟,app创建timer会用到这个时钟configure_rtc(qemu_find_opts_singleton("rtc"));// 解析目标机的内存参数parse_memory_options();
2.7 创建machine
2.7.1 new一个machine类型出来
current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class)));
- 这里看代码不方便,直接vscode上调试神器gdb,使用方法和参数见本系列第一章
- 直接断点打到vl.c/qemu_create_machine
- 在经历下图的调用堆栈之后,最后create machine进入hw/arm/virt.c中的virt_instance_init()函数,没毛病,因为我们machine参数指定的就是-M virt这个machine
2.7.2 设置memory page size
- 搞过驱动的都知道,为了系统效率,系统分配内存有个最小粒度,哪怕你只分1个字节,都要对齐到这个最小粒度上
- 所以这里也在设置系统的内存粒度,我的主机上page size是4kb,对应的page bits就是12,4kb=2^12