本文主要是介绍【QEMU系统分析之启动篇(十九)】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
系列文章目录
第十九章 QEMU系统仿真的加速器上电后设置分析
文章目录
- 系列文章目录
- 第十九章 QEMU系统仿真的加速器上电后设置分析
- 前言
- 一、QEMU是什么?
- 二、QEMU系统仿真的启动分析
- 1.系统仿真的初始化代码
- 2.主循环数据初始化
- 3. os_setup_post()
- Windows 系统 os_setup_post()
- POSIX 系统 os_setup_post()
- change_root()
- change_process_uid()
- 总结
前言
本文以 QEMU 8.2.2 为例,分析其作为系统仿真工具的启动过程,并为读者展示各种 QEMU 系统仿真的启动配置实例。
本文读者需要具备一定的 QEMU 系统仿真使用经验,并对 C 语言编程有一定了解。
一、QEMU是什么?
QEMU 是一个通用且开源的机器模拟器和虚拟机。
其官方主页是:https://www.qemu.org/
二、QEMU系统仿真的启动分析
1.系统仿真的初始化代码
QEMU 作为系统仿真工具,其入口代码在 system/main.c 文件中,初始化函数 qemu_init() 的实现在 system/vl.c 文件中,在完成 QEMU 虚拟机导出信息的设置,接下来将处理设置的后续工作,本篇文章将完成以下代码部分的分析。
2.主循环数据初始化
这部分代码在 system/vl.c 文件中,实现如下:
void qemu_init(int argc, char **argv)
{
...os_setup_post();
...
}
3. os_setup_post()
函数 os_setup_post() 根据宿主机系统不同而不同,
Windows 系统 os_setup_post()
在 Windows 系统上此函数在 /include/sysemu/os-win32.h 文件中,定义如下:
static inline void os_setup_post(void) {}
这是一个空语句,表示在 Windows 平台上不需要做额外操作。
POSIX 系统 os_setup_post()
在 POSIX 系统上此函数在 /os-posix.c 文件中,定义如下:
void os_setup_post(void)
{int fd = 0;if (daemonize) {if (chdir("/")) {error_report("not able to chdir to /: %s", strerror(errno));exit(1);}fd = RETRY_ON_EINTR(qemu_open_old("/dev/null", O_RDWR));if (fd == -1) {exit(1);}}change_root();change_process_uid();if (daemonize) {uint8_t status = 0;ssize_t len;dup2(fd, 0);dup2(fd, 1);/* In case -D is given do not redirect stderr to /dev/null */if (!qemu_log_enabled()) {dup2(fd, 2);}close(fd);do { len = write(daemon_pipe, &status, 1);} while (len < 0 && errno == EINTR);if (len != 1) {exit(1);}}
}
在 POSIX 系统中,需要做后台化处理,并完成标准输入输出设备的重定向。
change_root()
函数 change_root() 在 /os-posix.c 文件中,定义如下:
static void change_root(void)
{if (chroot_dir) {if (chroot(chroot_dir) < 0) {error_report("chroot failed");exit(1);}if (chdir("/")) {error_report("not able to chdir to /: %s", strerror(errno));exit(1);}}}
change_process_uid()
函数 change_root() 在 /os-posix.c 文件中,定义如下:
static void change_process_uid(void)
{assert((user_uid == (uid_t)-1) || user_pwd == NULL);assert((user_uid == (uid_t)-1) ==(user_gid == (gid_t)-1));if (user_pwd || user_uid != (uid_t)-1) {gid_t intended_gid = user_pwd ? user_pwd->pw_gid : user_gid;uid_t intended_uid = user_pwd ? user_pwd->pw_uid : user_uid;if (setgid(intended_gid) < 0) {error_report("Failed to setgid(%d)", intended_gid);exit(1);}if (user_pwd) {if (initgroups(user_pwd->pw_name, user_pwd->pw_gid) < 0) {error_report("Failed to initgroups(\"%s\", %d)",user_pwd->pw_name, user_pwd->pw_gid);exit(1);}} else {if (setgroups(1, &user_gid) < 0) {error_report("Failed to setgroups(1, [%d])",user_gid);exit(1);}}if (setuid(intended_uid) < 0) {error_report("Failed to setuid(%d)", intended_uid);exit(1);}if (setuid(0) != -1) {error_report("Dropping privileges failed");exit(1);}}
}
总结
以上分析了 QEMU 系统仿真在启动过程中,QEMU系统仿真上电后宿主系统相关设置的代码部分。
这篇关于【QEMU系统分析之启动篇(十九)】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!