谁来定义虚拟化? 一个比较抽象的词,很难给出一个比较明确的定义,而且我也一直认为没有人可以对一个抽象的概念给出绝对正确的定义。如果一个公司想争夺一种技术的定义权,我会毫不吝啬的给它扣上“技术独裁者”的帽子。 但是理解一个词在当前这个时代、这个世界的用法还是很有必要的,比如“虚拟化”这个词,对虚拟化开始重点关注以来,对“虚拟化”这个词的理解的确是在逐渐变化的,今天就来说一说我目前为止的理解。 从虚拟机说起 关注虚拟化方向之前,我对虚拟化这个词的理解是经历了几个阶段的。最开始可能“虚拟机”啊,有了虚拟机,大家就能方便地在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) […]

“新司机”虽然上路了,但并不知道走了多少弯路,因为还知道有没有走上正路。但上路也快一年了,当然有一些体会,就算是错的,也该想过些什么。如果我什么体会都不写出来,那么这些想法总会在我的脑子中绕啊绕啊的。所以我希望写些出来,也许这样就可以不用刻意提醒自己不要忘记它们,也好专心”开车”。而且我想,车技总是不断积累联系和回看总结的过程,也许我将来看现在自己的体会,不是嘲笑自己的车技太差就是羡慕自己的没有迷路运气。当然还有一种情况,就是我能因这些感想能将其他”新司机”带上(歪)路,我也是很欣慰的。。。 这系列文章,不去反省自己的缺陷,不去叙述自己的经历,只写下当前所总结的体会。本篇博客,我将写一下对存储栈的理解。后边,我还可能从存储组织(文件系统/存储结构)、存储缓存和虚拟化存储等几方面写下体会。 1. 层次化封装 就像OSI网络参考模型一样,存储也是有层次的,如果在网络中我们将这些层次称为网络协议栈(TCP/IP协议栈),那么在存储中我们经常用存储栈(storage stack)或I/O栈(I/O stack)与之对应。 顾名思义,栈这一种直上直下一层叠一层的结构。在网络的层次中,数据链路层关心的是MAC地址,网络层关心的是IP地址,栈中的所有层次分工协作,大家像流水线一样将数据层层传递如下图。 在存储层次中,也有类似的分工。比如以Linux存储栈为例,文件系统主要关心的是文件的组织结构,向上将接口暴露给用户;而文件系统下一层的块存储设备层则关心实际数据的去向,主要和存储设备打交道。下图是一个单机上比较复杂的情况,以一个运行在KVM虚拟机中的MySQL为例。当然如果考虑远程网络分布式存储,应该更复杂。 2. 为什么层次是必要的 除了网络和存储,其实编程语言中封装的这种概念,在我看来就类似这种层次化的形式。比如在很多编程语言中常用的SHA256、MD5等安全Hash算法或者链表、各种常用数据结构的库等。这节的问题就以编程中的封装和层次开发为例进行说明。 对编程语言的库来说,问题在于,既然哈希算法的计算方法都是开源的,数据结构都是固定的形式,为什么不自己写呢?首先想到的可能是自己写费时费力,其次一个被很多人使用的库一般都是由各路大神优化而来,应该比自己实现的效果要好,但最重要的,库是可以复用的。 比如那么当我们在这些其他人实现的库的基础上构建自己的应用的时候,就是在库的封装之上进行的开发,这就形成了库–>我的应用的这样的层次结构。进一步说,如果我们是在其他人的库的基础上开发了更高层的库,比如我在其他人写的二叉树库的基础上开发了用于排序的库,那么我们的封装层次就又涨了一层:二叉树库–>排序库–>其他人的应用。再展开说,我们甚至可以冲破一种编程语言的界限,表示出更完整的封装层次:数字逻辑–>指令集–>汇编语言–>系统调用–>编程语言标准库–>二叉树库–>排序库–>其他应用。 如果只是从左到右或者从上到下画出这种层次图,我们还是无法理解层次的必要性,但是如果我们想横向扩充,这种层次就是很必要的。极端的情况:如果我们所有的层次都重叠在一起,那么也许我想开发一个gui小应用,就要从汇编开始,一直沿着操作系统改到库和应用逻辑,简直不现实,这也是软件工程中耦合和内聚的概念。换句话说,不论我们是靠近硬件还是靠近应用的程序员,我们都可以从自己出发,只要向上层和下层提供不变的接口,那么不论我们在自己的范围怎么折腾,都不会破坏其他层次的工作。 回到存储,我们只有将管理文件的file system和下层的设备驱动通过块设备层和虚拟文件系统(VFS)层解耦,才能在单独编写多中设备驱动不用再去修改文件系统代码,也才能在添加新的文件系统功能的同时不用担心对老的设备是否可以工作。 3. 为什么层次可能影响性能 还是以编程语言为例,很多都认可C语言相对其他语言是高效的,但学汇编的人可能觉得汇编才是最高效的,这都没有错,汇编比C高效,但并不属于高级程序语言,C比Python高效,但是指针这种东西没有谁可以一时半会搞定。实际上,汇编–>C–>Python就可以认为是这样封装起来的。某种程度上来说,我们开发C语言应用可以看成是和开发Python是在一个层次上的。。。对于存储也是一样的,层次总是一层一层网上堆的。堆到越上层,越具有其简单易用的特性,而这种层次化页必然会带来性能上的降低。 现在在我看来,存储层次升高带来的性能损失的根本原因是因为在层次间信息的不对称的同时还有些层次要越层”搞事情”。具体来说,层次之间的沟通通过接口,由于层次间较松的耦合,某一层中无法获知其他层中的具体细节。比如,应用程序可能要告诉文件系统具体要读的文件名,但并不知道文件具体存在什么地址;文件系统可能告诉块设备驱动它具体要读内容的地址,但是块设备层就不知道这内容属于什么文件了。 但是,存储的管理不光“你告诉我你要什么数据,我把数据传给你”那么简单:首先,由于数据的重要性,各个层次都要用自己的机制保证数据的完整性和一致性;其次,也要利用数据的局部性,用dram作为cache来弥合内存和二级存储设备间的性能差异。那么大家都要保证数据可靠,大家也都在加把劲降低IO读写延迟,真的是齐心协力力量大吗? 当然大家都想整个系统变得更好,但是既然层级之间信息不对称,一定会因为缺少合作,而导致自己所做的工作不如预期,甚至起到副作用。我们是需要加强各层间的耦合交互?还是提升各层的“智能”让其揣测其它层的想法?还是应该聘请一个“存储栈独裁程序”来统一发出号令?这块儿学问就大了,还是新司机的我理解并不够深入,车技提升后还要展开多写写。。。 4. 在适当的层次做适当的事 Python认为程序员要指针没啥用,于是没有设计出指针的概念。而可能在一些C语言程序员眼中,Python因此就是一种有缺陷的语言。但是我们可能忽略了一点,就是没有谁禁止过Python程序员学习C语言,也没有人禁止过C程序员学Python。对于一个项目来说,没有最好的语言,只有最合适的。 对于存储层次同样如此,比如同样是数据加密,我们可以在应用程序中加密数据,可以在文件系统中加密数据,可以在数据网络传输之前进行,极端的情况,甚至也可以在硬盘硬件中进行加密。对于cache,我们可以在应用层开辟内存作为cache、或者利用文件系统缓存,或者磁盘的硬件缓存等。选择很多,不同的功能,适合的位置也是不同的,同样和上节一样,这块儿学问就大了,还是新司机的我理解并不够深入,车技提升后还要展开多写写。。。

原文出处: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 […]

译者的废话 这是Red Hat RHEL 7文档中关于KVM虚拟机超量分配的说明文档,这里说的KVM,应该就是适用QEMU管理的KVM虚拟机的,因为在启动QEMU虚拟机的时候,只要-smp N和-m N参数分别就可以指定虚拟机的vCPU数和内存数,我实际实验发现,它们是都可以超过实际的物理CPU核数和内存大小的。 硬件资源超量分配,说的好听是节约资源,但是资源的分配超的不切实际,也就是”VPS超售”的万恶之源。。。比如一个4核8G内存的服务器,碰上黑心商家,不知道会被分出多少个1核1G内存的小崽子呢。。。不过这里Red Hat只是给出技术上的建议,没有提及VPS超售问题。嗯,做技术,不可耻。。。 原文: https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Virtualization_Deployment_and_Administration_Guide/chap-Overcommitting_with_KVM.html#sect-Overcommitting_with_KVM-Introduction 简介 KVM hypervisor支持CPU和内存的超量分配。超量分配就是划分的虚拟CPU(vCPUs)或者内存比系统的实际物理资源多。通过CPU的超量分配,使用中的虚拟服务器或桌面就可以在更少的服务器上跑了,节省了不少系统资源,同时会减少电源、冷却等硬件方面的投资。 由于大多数进程始终不能访问其分配的内存的100%,因此KVM虚拟机可以利用此行为来分配给客户机虚拟机的多于实际可用的内存空间。 内存的超量分配 注意!

要理解甚至修改Qemu,肯定要会编译它,不能老是apt-get,所以做个流程记录,并带上简单的解释。 1. 下载源码 http://wiki.qemu.org/Download 从这里下就可以了 2. 解压 比如我下载的是qemu-2.8.0.tar.bz2 # 解压 tar -xvf qemu-2.8.0.tar.bz2 # 进入源码目录 cd qemu-2.8.0 3. 配置 # 配置 ./configure [–enable_debug –prefix=/PATH/TO/INSTALL –target-list=x86_64-softmmu]

系统概况: host 和 guest 都是用的 Ubuntu Server 16.04系统。 我的 host 机上有三块网卡2块有线网卡(接口 enp1s0 和 enp3s0)和1个无线网卡(接口 wls2s0)。 我的 host 机通过无线网卡连在一个路由器上,并因此能够连接到互联网,所在的网段是192.168.3.0\24,ip 固定为192.168.3.5。 其他两块有线网卡没有连接。 实验0: 效果: guest 与 guest、guest 与 host 之间可以互相 ping 通;guest 不能访问 host 所在路由器网段(192.158.3.0\24)。 方案: 在 host 中搭建了一个虚拟网桥,将 qemu-bridge-helper 工具在启动虚拟机时创建的虚拟网络接口 tap0[1,2…] 与 host 桥接在一起,我手动配置了他们的网段是192.168.4.0\24。 步骤: 1.配置 host 的 /etc/network/interfaces ,在其中加入以下内容,然后通过 /etc/init.d/networking restart 重启服务来创建网桥。 auto br0 iface […]

刚想玩玩kvm,结果分不清这几个命令。。搜了一下,记录下来,希望对大家有帮助。 摘抄 1 在老版本中有单独的qemu-kvm模块存在,结合qemu一起做虚拟机工作。在后续新版本中,已经将qemu-kvm模块完全合并到qemu中去。因此当需要使用kvm特性时候,只需要qemu-system-x86_64 启动命令中增加参数 –enable-kvm参数使能即可。 (http://blog.csdn.net/tantexian/article/details/41281171) 2 I asked the mailing list, here’s what I got: qemu-arch like /usr/local/bin/qemu-x86_64 is for running a program of that arch on the host machine of what ever arch, but not a virtual machine qemu-system-arch like /usr/local/bin/qemu-system-x86_64 is for running a system of that arch on the host […]