Technically, KVM-based VM is a special type of virtual machine which relies on physical machine features. Following lists some popular VM types that do not use KVM. Hope you also find it interesting. VM Name Translation Technologies Executable Format Runtime Dalvik VM (Register based VM) Interpretation Android (<2.2, 2008) Dalvik VM JIT + Interpretation (Just […]

What is a “Container Runtime” ? As already explained in a previous blog (容器生态技术栈 – JciX ~), container runtimes are the components that will take the responsibility to run the container. They will be invoked by container engines (like containerd, and CRI-O), and will create the containers using Linux kernel primitives (like cgroups, and namespaces). […]

汇总一些容易混淆的容器领域技术概念,希望对你有所帮助。 技术栈架构 生态对比 Ecosystem Orchestration Service Orchestration Agent Container Engine ContainerRuntime CLItools OCI / CNCF k8s kubelet containerd(CRI runtimes) runc / kata(OCI runtimes) ctr,crictl Docker docker swarm dockerd(docker CLI) containerd runc docker LXD /Canonical clusterd lxd lxd lxd lxc lxc OpenShift / Redhat k8s kubelet CRI-O runc podman 当然,这里列出的只是各个生态的默认技术栈,开源社区中还有各种项目让不同生态的组件互相组合协同工作。比如:Mirantis/cri-dockerd: dockerd as a compliant Container Runtime […]

原文为vfio mediated device内核文档[5],我翻译一下。 1. Virtual Function I/O (VFIO) Mediated devices[1] 对没有内置SR-IOV功能的设备进行DMA虚拟化的需求越来越多。以前,为了虚拟化一个这样的设备,开发者需要自己开发管理接口和API,然后把它们集成到用户态应用中。为了简化这种用户空间软件集成,我们找出了这种设备公共需求然后开发了一种统一的接口。 VFIO驱动框架为直接设备访问提供了统一的API。它将设备直接访问安全地(以一种IOMMU保护的环境)暴露给用户,是一种IOMMU/设备无关的框架。此框架用于多种设备,如GPU、网卡和计算加速器等。有了这种直接设备访问,虚拟机或者用户态应用可以直接访问物理设备。Mdeiated devices便是重用了VFIO这种框架。 Mediated core driver为mdiated device提供了一个公共的管理接口,它可以被不同类型的设备驱动所利用。这个模块提供了的通用接口可以进行如下操作: 创建和删除mediated device 把一个mediated deivce加入或移出某个总线驱动 把一个mediated device加入或移出某个IOMMU group Mediated core driver也提供注册总线驱动的接口。比如,一个mediated VFIO mdev驱动就是为mediated devices设计的,并且支持VFIO的API。Mediated bus driver可以将一个mediated device加入或者移出一个VFIO group。 以下的上层图展示了VFIO mediated driver框架的主要组件和接口。这张图展示了NVIDIA、Intel和IBM设备,因为这些设备是首先使用这些模块的。 +—————+ | | | +———–+ | mdev_register_driver() +————–+ | | | +<————————+ | | | mdev | | […]

(翻译自qemu 3.0的文档) qemu-img [standard options] command [command options] qemu-img 允许你离线地创建、转换或者修改镜像文件。它可以处理所有QEMU支持的镜像格式。 注意: 千万不要用 qemu-img 修改虚拟机(或者其他程序)正使用着的镜像,因为那可能会破坏镜像;对应的,如果读正在修改的镜像,也可能会有不一致的状态产生。 1. Standard options: ‘-h, –help’ 显示帮助信息。 ‘-V, –version’ 显示版本信息。 ‘-T, –trace [[enable=]pattern][,events=file][,file=file]’ Specify tracing options. 指定tracing选项: ‘[enable=]pattern’ 以parttern来指定启动的events。这个选项仅在编译了simple、log或ftrace等3个tracing后端时才能用。要启用多个events或者patterns,用多个-trace即可,用-trace help可以打印列出trace points名称。 ‘events=file’ 马上开启file中列出了的events名称,file中每行为一项event名称或者patterns (存在于trace-events-all文件中的)。同样,这个选项仅在编译了simple、log或ftrace等3个tracing后端时才能用。 ‘file=file’ 将traces的输出打印到log文件中。同样,这个选项仅在编译了simple、log或ftrace等3个tracing后端时才能用。 2. Command: 以下是被支持的命令: amend [–object objectdef] [–image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename […]

我们应该怎么分析QEMU代码中某段代码的性能呢?除了比较复杂的trace-event功能(我的博客中翻译过qemu tracing的文档),其实在QEMU自带有一个简单的profiler实现,它是一个简单的计时器封装。这篇博客主要介绍怎么在编译时开启、使用QEMU profiler,并说明怎么利用这个功能添加一个自己的计时器来分析QEMU中某段代码的性能。 1. 编译 我的代码是QEMU 2.12.0。要开启profiler功能,在编译前进行运行configure的时候,只要加入–enable-profiler选项就可以了,它会加入CONFIG_PROFILER这个宏定义。比如我用如下选项进行编译: cd QEMU_SRC_PATH ./configure –prefix=/PATH/TO/QEMU_BIN_DIR –target-list=x86_64-softmmu –enable-profiler make -j make install 将其编译到QEMU后,无须改动启动参数,它是默认启用的,但是我们一般需要用QMP shell来查看它帮我们计时的信息。 2. 使用 在启动QEMU虚拟机的命令中,我们需要加入一个QMP socket,用于一会接入我们的QMP shell: # -qmp后边接我们要创建的QMP socket文件的信息,这里我们将它创建在本目录(./qmp-sock文件) /PATH/TO/QEMU_BIN_DIR/bin/qemu-system-x86_64 … -qmp unix:./qmp-sock,server,nowait 在虚拟机启动后,用QEMU源码中自带的QMP shell脚本连接QMP socket: # 这个脚本就是QEMU源码中的scripts/qmp/qmp-shell文件 # 加-H是为了以HMP命令进行交互,否则就得使用json格式,不方便 /PATH/TO/QEMU_SRC/scripts/qmp/qmp-shell -H ./qmp-sock 之后出现以下欢迎界面: Welcome to the HMP shell! Connected to QEMU 2.12.0 (QEMU) 我们在(QEMU)后面输入info profile就可以看到QEMU自带的两个计时器的数值,每次查看完这个数值,数值会清零。 Welcome […]

谁来定义虚拟化? 一个比较抽象的词,很难给出一个比较明确的定义,而且我也一直认为没有人可以对一个抽象的概念给出绝对正确的定义。如果一个公司想争夺一种技术的定义权,我会毫不吝啬的给它扣上“技术独裁者”的帽子。 但是理解一个词在当前这个时代、这个世界的用法还是很有必要的,比如“虚拟化”这个词,对虚拟化开始重点关注以来,对“虚拟化”这个词的理解的确是在逐渐变化的,今天就来说一说我目前为止的理解。 从虚拟机说起 关注虚拟化方向之前,我对虚拟化这个词的理解是经历了几个阶段的。最开始可能“虚拟机”啊,有了虚拟机,大家就能方便地在Windows下用Linux系统啦。后来云计算火起来了,云服务器的底层技术是什么啊,是虚拟机和虚拟化啊,所以感觉虚拟化真是很牛逼。后来Docker火了,Docker是什么,人家都说是“轻量级的虚拟化”,哇,虚拟化这么牛逼,虚拟机、云服务器、Docker都用了虚拟化啊。 虚拟机就像下面的图中,如果把一个计算机软硬件系统比作一个从地基垒起的金字塔(用户和应用在金字塔顶),那么虚拟机就像一个倒立的金字塔,虚拟机的用户就像是倒立的金字塔上的金字塔。要让一个虚拟机正常运转,就要在软件层面上模拟各种计算机硬件,涉及到计算,存储,网络等各种设备。 以QEMU为例,虚拟机的CPU是以QEMU创建的vCPU线程进行模拟的,这些线程仍然由Host操作系统进行调度;虚拟机的网络和存储IO是通过virtio这种半虚拟化机制达成的,Guest的IO通过内存的循环队列传递数据和消息;虚拟机的存储设备通过Host中的一个文件来进行模拟……但是虚拟机(Virtual Machine)所用的技术就是虚拟化技术(Virtualization)吗?我认为不一样。 虚拟机之外的虚拟化 以存储虚拟化(Storage Virtualization)为例,Linux逻辑卷管理技术(LVM),有了这种技术,我们可以将多个分区虚拟成一个大的逻辑分区,或者将一个分区虚拟成多个小的逻辑分区。LVM之外,Linux中的loop回环设备(将一个文件虚拟成一个块设备)、tmpfs(将一段内存虚拟成一个文件系统分区)、RAM DISK(将一段内存虚拟成一个块设备)、UnionFS(将多个文件系统虚拟成一个文件系统)在我理解都应该属于虚拟化之列。而QEMU虚拟机中,我们多是把一个文件虚拟成一个磁盘,其灵活性无法代表整个存储虚拟化技术,或者说仅关注QEMU,我们不能关注到所有的存储虚拟化技术。 QEMU VM的vCPU是Host操作系统中的线程,可以看做是计算的虚拟化。其实按照广义的虚拟化,Intel的超线程(Hyper-threading)技术岂不更加“虚拟”?比如它可以将一个核抽象成操作系统看来的两个核。 虚拟化,无处不在 更广义(准确)的,其实操作系统技术本身就是虚拟化技术,没有操作系统的进程调度时间片切换,也许CPU是1核的就只能同时跑1个程序,但有了操作系统,你不仅能同时照着网页抄作业、还能看着paper听着歌。这一切都是系统将计算资源虚拟化的结果啊。 再说编程语言,程序员之所以不用编写二进制代码,便是因为有工具可以将高级语言翻译成机器码,如果不去研究编译器,这种翻译也是透明的;编程语言,形形色色,不管你用哪种,其实背后都是0,1在执行(电位在变化)。我可以在这篇博客里写一串二进制码011110100110101001100011,你看到的0和1并不是底层的0和1,但还是0和1,不也是类似虚拟机软件反向搭建金字塔的过程吗?同样,人类语言也可以看成是思想的“虚拟化”。 所以,什么是虚拟化?虚拟化,道也,什么是道?老子说,“道可道,非常道”。

0. GCC的attribute关键字 这是GCC的一个特性,gcc可以使用attribute关键字,格式如下: __attribute__((attribute_name)) 其中attribute_name中有两类constructor和destructor类似C++中类的构造和析构的概念,只不过是相对main()函数来说的。简单说,__attribute__((constructor))定义的函数在main前执行,__attribute__((destructor))定义的函数在main后执行。 1. 以qcow2为例 QEMU中有很多”module”的初始化使用了__attribute__((constructor))这个特性,来在main前完成init函数的注册过程。使用方法举例具体如下: // QEMU_2.10_SRC/include/qemu/module.h中: #define module_init(function, type) \ static void __attribute__((constructor)) do_qemu_init_ ## function(void) \ { \ register_module_init(function, type); \ } #endif typedef enum { MODULE_INIT_BLOCK, MODULE_INIT_OPTS, MODULE_INIT_QOM, MODULE_INIT_TRACE, MODULE_INIT_MAX } module_init_type; // 比如这里block_init函数被用在QEMU_SRC/block/*的qcow2等Format Driver中广泛应用, // 其实就是间接调用了被__attribute__((constructor))调用的register_module_init() #define block_init(function) module_init(function, MODULE_INIT_BLOCK) #define opts_init(function) module_init(function, MODULE_INIT_OPTS) #define type_init(function) module_init(function, MODULE_INIT_QOM) […]

原文出处:QEMU当前的文档 qemu/docs/devel/tracing.txt 一、介绍 这篇文档描述了QEMU追踪的整体架构和如何使用追踪功能来进行debug、性能分析或者监测运行状况。 二、快速开始 步骤1. 编译QEMU时带上’simple’trace追踪后端: ./configure –enable-trace-backends=simple make 步骤2. 创建一个写有你想追踪的事件(events)的文件 echo memory_region_ops_read >/tmp/events 步骤3. 运行虚拟机来产生一个追踪文件 qemu -trace events=/tmp/events … #加上其他你需要的qemu选项参数 步骤4. 以美观的形式打印出二进制的追踪文件Pretty-print the binary trace file: ./scripts/simpletrace.py trace-events-all trace-* #用QEMU的进程号(pid)来代替”*” 三、Trace events 1. 设置子文件夹 Sub-directory setup 在源码目录的每个文件夹中都可以在trace-events文件中声明一组静态的trace events。所有包含有trace-events文件的子文件夹必须被列在源码根目录Makefile.objs的trace-events-subdirs项中。这样在编译时,被列出的子文件夹的trace-events文件就会被tracetool脚本处理来生成相关的追踪代码。 单独的trace-events文件会被merged到一个trace-events-all文件中,trace-events-all文件也将会被安装到/usr/share/qemu目录中,并改名为trace-events,这个文件最终会被simpletrace.py脚本用作simpletrace数据格式的追踪分析。 在子文件夹中,以下的文件会被自动生成 trace.c – the trace event state declarations trace.h – the trace event enums […]