Xen 虛擬機架構

作者: 董耀祖  發布時間: 2013-02-27 18:34  閱讀: 19813 次  推薦: 5   [收藏]  

  [Abstract]
  Xen 是一個基于開源軟件組織的虛擬機監控器(即 Virtual Machine Monitor 簡稱 VMM),可以允許在單一的物理機器上同時運行多個操作系統實例。

  虛擬化技術概述

  虛擬計算機的概念最早由 IBM 公司在上世紀六七十年代提出,并將其運用于 VM/370 系統中以共享昂貴的大型機系統(Main Frame)。之后的發展起起伏伏,一度由于分時操作系統的出現而處于停滯狀態。上世紀九十年代隨著 JAVA 虛擬機的推出,尤其是之后 Vmware 公司 Vmware ESXserver 和 Vmware workstation 虛擬機的推出,使對虛擬機技術的研究再次成為處理器設計人員、軟件設計人員、服務器設計人員和網絡安全設計人員的熱門研究課題。

  如圖 1 所示,虛擬化技術通過在現有平臺(機器)上添加一層薄的虛擬機監控程序(Virtual Machine Monitor,簡稱 VMM)軟件而實現對系統的虛擬化,如虛擬處理器,虛擬內存管理器(MMU)和虛擬 I/O 系統等。虛擬機監控程序又被稱之為監管程序(Hypervisor)。從應用程序的角度看,程序運行在虛擬機上同運行在其對應的實體計算機上一樣。虛擬機技術使得一臺物理計算機可以生成多個不同的虛擬機分別運行多個不同或相同的操作系統。虛擬機技術通過將不同的應用運行在不同的虛擬機上,可以避免不同應用程序之間的互相干擾,例如一個應用的崩潰不會影響到其它的應用等。這種由虛擬機技術實現的各個應用之間的完全隔離在服務器領域具有尤其重要的意義,同時虛擬機技術也可以使得企業、高校或研究所可以在不必購置大量物理計算機的情況下實現大規模的計算機網絡以從事生產及研究,例如網絡及網絡應用研究,操作系統內核(Kernel)軟件的開發和用戶操作系統的開發等。

  VMM 抽象的虛擬機的指令集(Instruction Set Architecture 簡稱 ISA)可以等同于它運行的物理機器,也可以作些微修改。當虛擬的指令集與物理的指令集相同時,該虛擬機可以運行沒有任何修改的操作系統;而當兩者不完全相同時,客戶機的操作系統就必須在源代碼級或二進制代碼級作相應修改。根據是否需要修改客戶機操作系統的源代碼,虛擬化技術又可以分為(1)泛虛擬化(Paravirtualization)和(2)完全虛擬化(Full-virtualization)。完全虛擬化由于不需要修改客戶機操作系統,因此具有很好的兼容性和同時支持異種操作系統或不同版本操作系統的能力。相反泛虛擬化技術則通常具有比完全虛擬化技術更好的性能。

  泛虛擬化技術在最早的 IBM VM/370 上就已經使用,但它的使用僅僅是為了支持傳統的操作系統,因此被限制在很小的范圍。美國華盛頓大學計算機科學與工程系的 Steven D. Gribble 領導的 Denali 項目和英國劍橋大學計算機實驗室的 Ian Pratt 和 Keir Fraster 領導的 Xen 項目組實現了 X86/PC 上的泛虛擬化,使泛虛擬化技術重新成為最熱門的虛擬化技術之一。隨著 Intel® 公司在 2005 年初推出基于處理器硬件的虛擬化技術(Intel® Virtualization Technology 簡稱 Intel®VT 技術),支持未經修改的操作系統的完全虛擬化技術同泛虛擬化技術一樣成為當今虛擬化領域中的兩個主要研究方向。

  Xen 虛擬機

  Xen 是一個基于開源(Open Source)代碼的系統虛擬機,最初基于 32 位 X86 體系結構而設計開發,支持同時運行多至約 100 個虛擬機。Xen 引入的管理接口(Hypercalls)和事件(Events)機制,以及預先定義的虛擬機和 VMM 之間的共享內存數據交換機制都使得新的客戶機體系架構(Xen 虛擬機架構)具有更高的總體性能,但同時也就注定了它必須修改客戶機操作系統源代碼。

  Xen 將客戶機稱之為虛擬域 (Domain),其中 0 號虛擬域為服務域作為監控程序的擴展提供系統的管理服務。監控程序擁有部分硬件 IO 資源如定時器設備、中斷設備PIC/Local APIC/IO APIC 等,其他虛擬域也可以擁有部分的 IO 資源,如硬盤網卡等。擁有物理設備的虛擬域稱為隔離設備驅動域(Isolated Driver Domain)或簡稱設備驅動域(Driver Domain)。普通虛擬域只有虛擬設備而不擁有直接的硬件設備資源訪問權。Xen 項目也將 Hypervisor 稱為 Xen。

  Xen 本身主要基于開源的 Linux 內核代碼移植而來,同時運行其上的 XenLinux 也從 Linux 移植而來,意為支持 Xen 架構的Linux。同樣支持 Xen 架構的 FreeBSD 和Windows XP 也能夠在 Xen 上運行。應用程序(X86)均不需任何修改就可以在 Xen(X86) 上運行,如 Linux 應用程序可以在 XenLinux 上運行而 Windows XP 應用程序可以在 XenXP 上運行。

  Xen 泛虛擬化體系結構

  Xen 監管程序(hypervisor)運行在最高優先級(Ring 0)上,泛虛擬化的客戶域運行在較低的優先級上(Ring1-3 )。Xen/X86 泛虛擬化域的內核運行在優先級 1 上,而應用程序仍然運行在優先級 3 上。Xen 服務虛擬域擁有對整個(或部分)物理系統資源的管理功能,如塊設備,顯示和輸入輸出等。

  Xen 支持泛虛擬化域和完全虛擬化域的同時運行,如圖 2 所示。虛擬域0(即服務虛擬域)作為 hypervisor 的擴充,直接擁有系統硬件輸入輸出設備(IO,DMA等),也因此必須具有對這些設備響應的原生(Native)驅動程序。虛擬域0提供對整個系統的管理平臺,也是一個設備驅動域。虛擬域1是一個設備驅動域擁有部分物理設備,因此也需要 Native 驅動程序以及向其它客戶機提供后端設備驅動程序。虛擬域2是一個用戶泛虛擬化域,它不具有物理硬件設備,相反通過虛擬設備(即前端設備驅動程序)向位于虛擬域 0 的后端設備驅動程序申請服務而實現對設備的訪問。另外,未經修改的操作系統上也可以運行泛虛擬化的前端設備驅動程序以獲取更高的性能。

  事件通道(Event Channel)

  事件通道是 Xen 用于虛擬域和 VMM 之間、虛擬域和虛擬域之間的一種異步事件通知機制。在 32 位 X86 架構下共有 1024 個事件通道,共分 8 組,每 128 個通道一組。Xen 架構上的物理中斷 (pIRQ) 、 虛擬中斷(vIRQ)、虛擬處理器間中斷(vIPI)和虛擬域間通信(Inter Domain Communication 簡稱IDC)均通過事件通道實現。向事件通道發送消息會在每一個虛擬域的內部數據結構(evtchn_pending)中置位以便客戶機處理。如果目標虛擬處理器正在運行則需要通過物理 IPI 打斷當前虛擬機的執行,以及時響應異步事件。

  Xen 架構上的物理中斷等同于原生系統上的中斷,使擁有原生設備的 Xen 虛擬域可以最大程度地利用原生操作系統(Linux)的設備驅動程序。事件通道機制使得 hypervisor 在向客戶機異步通知時可以一次承載多個異步事件(含物理中斷),從而一次虛擬域與 hypervisor 之間的邊界穿越可以使客戶機批處理多個中斷事件,大大提高了系統的總體性能。

  泛虛擬域對虛擬中斷和物理中斷的處理完全一樣,在 Linux 中它們都由 do_IRQ 中斷服務程序處理。同時將整個系統的中斷數目相應增加到 512 個,其中的前 256 個為物理中斷使用以保持與原生系統的相似性,后 256 個為虛擬中斷使用。

  Hypervisor 服務(Hypercall)

  Xen 虛擬域本身并不能直接訪問本虛擬域以外的物理資源,包括 hypervisor 本身,但是虛擬域可以通過 hypercalls 向監管程序申請各種服務。Hypercalls 就如同傳統操作系統下的系統調用,監管程序通過它向各虛擬域提供各種服務,如 MMU 更新(do_mmu_update)、dom0 操作(do_dom0_op)請求、虛擬處理器狀態(do_vcpu_op)等等。在 32 位 X86 架構下 hypercall 通過 int 0x82 陷阱(trap)指令實現,因為傳統操作系統本身并不使用 int 0x82(Linux 使用 int 0x80 作為系統調用指令,int 0x82 并未使用)。Hypercall 的具體功能識別號由 eax 表明,而其它參數則在 ebx, ecx, edx, esi 和 edi 中。為了減少虛擬域和 hypervisor 之間的特權級別(ring)切換次數,Xen 提供對 hypercall 的批處理,即將幾個 hypercall 功能請求放在一個列表中由專門的 do_multicall_call 請求完成。

  只有特權級別為1的代碼(泛虛擬化域的 kernel)才能向 Xen 發送 Hypercall 請求,以防止應用程序(特權級3)的錯誤調用導致對系統可能的破壞。因此只有運行在特權級1的虛擬域操作系統內核才能申請hypercall。但是一些 Xen 專用的特別程序如 xend 或 xm 也需要有 hypervisor 的服務來完成特殊的操作如生成一個新的虛擬域等,這在 XenLinux 中是通過一個稱為 privcmd 的內核驅動程序實現。應用程序通過 ioctl 向該驅動程序提出服務請求,運行在虛擬域內核(特權級1)的 privcmd 驅動程序再將服務請求以 hypercall 形式轉向 hypervisor 并由后者完成。

  Xen 硬件虛擬機體系結構

  泛虛擬化技術通過對客戶機操作系統的修改,繞開了傳統 X86 體系結構的虛擬化漏洞,并以良好的性能贏得了在開源軟件操作系統(如 Linux)上的廣泛關注,但是無法支持象 Windows 這樣的私有操作系統。硬件虛擬化技術在芯片硬件層面上彌補了 X86 體系結構的虛擬化漏洞,使 hypervisor 對未經修改的操作系統的支持成為可能,如 Intel®VT 和 AMD SVM 技術。

  Intel® VT 技術引入了一種新的處理器操作,稱為 VMX(Virtual Machine Extensions)。VMX 操作可以在根狀態(root)或非根狀態(non-root)下執行,通常虛擬機監控程序(VMM)在根狀態下執行而客戶機軟件則運行在非根狀態。VMM 可以通過虛擬機進入(VM entry)使處理器進入 VMX 非根狀態,相反通過虛擬機退出(VM exit)可以使控制權回到 VMX 根狀態。

  處理器處于 VMX 根狀態時的功能和權限就像沒有 VMX 的系統一樣,只是引進了一些新的支持 VMX 的指令,而處于非根狀態的處理器的行為則受到了限制。某些特定的指令,事件或狀態會導致虛擬機退出到 VMM 進行特權資源虛擬化,但客戶機軟件本身并不知道自己是否運行在虛擬機上。

  VMX 操作新定義了虛擬機控制結構(Virtual Machine Control Structure),簡稱VMCS。Xen 對硬件虛擬處理器的管理通過 VMCS 實現,如圖3所示。當虛擬機進入時(處理器控制從 VMX 根狀態進入 VMX 非根狀態),處理器狀態被保存在 VMCS 中(Host狀態),同時客戶機狀態從 VMCS 中裝入。相反當虛擬機退出時(從 VMX 非根狀態進入 VMX 根狀態),處理器狀態被保存在VMCS 的中(客戶機狀態),而 Host 狀態則從 VMCS 中裝入。VMM 可以對不同虛擬處理器的 VMCS 分別設置不同虛擬機退出條件,從而實現對不同客戶機的不同虛擬化策略。

  支持硬件虛擬機的 Xen 架構如圖4所示,在 64 位 VMM 上的 VMX 虛擬機可以同時支持 32 位客戶機和 64 位客戶機并存,并且運行在完全的(客戶機)特權級別上。運行在硬件虛擬機上的客戶機操作系統不需要任何修改,可以支持從開源的 Linux(2.4 版本和 2.6 版本) 到私有的 Windows (WindowsXP, Windows2000) 以及對這些操作系統的安裝。有報道指出 FreeBSD 也可以成功在 Xen 硬件虛擬機上運行。

  內存虛擬化

  每一個 X86 客戶機的內存地址總是從 0 開始的,而位于該地址的物理內存只有一塊。因此監控程序必須把客戶機從 0 開始的內存地址映像到其他物理內存頁,也因此監控程序必須把客戶機虛擬地址(guest virtualaddress)到客戶機物理地址(guest physicaladdress)的映像(客戶機頁表)進行重新映像,即建立客戶機虛擬地址到機器物理地址(machine physical address 或 physicaladdress)的映像。Xen 泛虛擬化實現采用修改客戶機頁表的方式實現這一重新映像,硬件虛擬機采用影像頁表(shadow page table)方式實現。

  Xen 泛虛擬化的 hypervisor 和客戶機共享同一個地址空間。32 位 X86(非 PAE 模式)架構下的 hypervisor 占有 4G 空間的高 64M地址空間即從 0XFC000000 到 0XFFFFFFFF,這通過重定向泛虛擬化客戶機的 GDT 表實現。hypervisor 為每一個虛擬域準備一個內部 GDT 表以容納客戶機 GDT,但同時為 Xen 保留一部分描述符空間用于 1) hypervisor 將自身的代碼和數據分別映像到 ring0, 1 和 3;2) 映像每一個 CPU 的 TSS;3) 映像每一個 CPU 的 LDT。因此泛虛擬化的 Xen 客戶機只能使用 0 到 4G-64M 的地址空間,這并不會影響 Linux 應用程序的正常執行(應用程序只使用 0-3G 地址空間)。

  Xen 虛擬域的初始內存大小在該虛擬域啟動時確定,各虛擬域以分區(partition)形式共享整個系統的物理內存。XenLinux 實現了氣球(ballon)驅動程序(如圖 5 所示)來調節各虛擬域之間的物理內存共享。當一個虛擬域 A 需要更多的內存時,它可以通過氣球驅動程序向 Hypervisor 提交內存請求,Hypervisor 可以在未分配的內存中或向其它虛擬域 B 通過氣球驅動程序回收內存而提供該 A。虛擬域 A 的氣球驅動程序在得到 Hypervisor 新提供的內存后向操作系統釋放。

  設備虛擬化

  除了處理器和內存,計算機的運行離不開外圍設備,如硬盤、顯示器、鍵盤鼠標等,同樣虛擬機的運行也離不開虛擬平臺上的各種各樣的設備。這些設備通常可以歸納成 3類:1) 泛虛擬化設備;2) 仿真設備;3) 直接分配設備(Direct Assignment)。泛虛擬化設備是一種存在于特定環境下(Xen)的一種完全虛擬的設備,它需要在客戶機操作系統上安裝全新的驅動程序以實現對虛擬設備的訪問;仿真設備則利用軟件方法仿真一個操作系統能夠識別的物理設備,通常也是現實世界中已經存在的設備,如 IDE 硬盤。對于仿真設備,客戶機操作系統及 BIOS 本身具有對該種設備的驅動程序,因此不需重新開發客戶機驅動程序;直接分配設備是指將一個系統上物理存在的設備,排他性地賦予一個虛擬機。如在一個有兩塊以太網卡的機器上,將其中的一塊排他性地賦予一個硬件虛擬機如 VMX 虛擬域。擁有直接分配設備的虛擬域即為隔離設備驅動域,如圖 2 中的虛擬域 1。

  Xen 虛擬設備

  如圖 2 所示,除了虛擬域 0 和隔離驅動域外,Xen 虛擬域 2 本身并不擁有真正的物理設備,而是虛擬設備,如虛擬的控制臺(輸入輸出),虛擬的塊設備甚至虛擬的網絡設備。Xenbus 為所有泛虛擬化的設備驅動程序在虛擬域之間的通信提供了一個抽象的總線,Xen 虛擬設備都必須在初始化時向 Xenbus 注冊,而將大部分的內部初始化和設置推遲到 Xenbus 探測(probe)時。Xen 常規的塊設備驅動程序分成前端驅動程序(Front-end driver)和后端驅動程序(Back-end driver),如圖 2 上的前端設備驅動程序在接到來自操作系統的讀寫請求時,通過事件通道和共享內存向位于隔離驅動域的后端設備提出服務請求。后端設備在收到服務請求后則通過該虛擬機上的原生設備完成讀寫請求。典型的 Xenbus 上虛擬設備包括虛擬塊設備(VBD)和虛擬網絡接口(VNIF)。

  仿真設備

  如圖 4 所示,在硬件虛擬機中,為實現物理設備的共享,客戶機的 I/O 訪問(含內存映像 I/O-Memory Mapped IO)必須被 Xen 捕獲,由設備模型(Device Model)進行仿真。硬件虛擬化技術提供了對客戶機 I/O 操作的捕獲支持,而對于內存映像 I/O,則通過頁缺失(Page fault)被 Xen 捕獲。但是 Xen 監控程序本身并沒有驅動程序去直接訪問這些設備,因此這些 I/O 訪問的仿真最終由 Xen交由虛擬域 0 完成。從客戶機操作系統的角度看,仿真設備同真實的物理設備并沒有區別。

  位于 Dom0 的設備模型(Device Model)向硬件虛擬機提供了一個虛擬的 PC 平臺(虛擬設備)。每一個硬件虛擬機都可以看到一個完整的虛擬 PC 平臺,包括鍵盤、鼠標、實時時鐘、可編程定時器(8254)、可編程中斷控制器(8259)、CMOS、軟盤、IDE 硬盤、CDROM和 VGA 圖形卡等。

  直接分配設備

  客戶機操作系統對直接分配設備的訪問就如同在原生系統上一樣。直接分配設備在本質上是一個不參與虛擬化的真實物理設備,客戶機對直接分配設備的 I/O 訪問直接傳送給物理設備,而物理設備產生的中斷也直接傳遞到該虛擬機,同時直接分配設備的 DMA 操作結果也必須可以直接被該虛擬機接受。

  運行在客戶機上的未經修改的操作系統本身并不知道監控程序已經將它的客戶機物理地址作了重新映像;另外,DMA 操作只支持小于 4G 的物理內存地址,這在 32 位虛擬機上沒有任何問題,但是在 36 位地址的PAE(Physical Address Extensions)模式和 64位機上則是一個大問題;因此未經修改的操作系統并不能夠支持直接分配設備。Xen 泛虛擬化域采用修改設備驅動程序的方法,將 DMA 操作的客戶機地址轉換成物理地址的方法實現物理設備的直接內存存取即 DMA。這在物理內存小于 4G 的系統上總能實現,但是對于物理內存大于 4G 的系統則未必可行,因為驅動程序得到的物理內存地址可能大于4G。Intel® 的設備虛擬化技術提供了基于硬件的解決方案,如圖 6 所示,通過引入硬件 DMA 地址重新映像的方法,將客戶機物理地址轉化成機器物理地址(設備 A 和 B 所用的 DMA 地址是客戶機物理地址), 從而實現對設備 DMA 的支持。Xen 硬件虛擬機采用的硬件設備虛擬化技術,通過 VMM 向硬件提供客戶機 DMA 物理內存到機器物理地址的映像頁表,實現未經修改的操作系統對直接分配設備的訪問支持。

  Xen 跨平臺支持

  Xen 作為一個開源的泛虛擬化解決方案,它的總體框架具有對其他處理器(X86以外)架構的支持。Xen 3.0 已經實現對 Intel® 安騰架構(Itanium)的支持(Xen/IA64),同時對 IBM Power PC 架構的支持也正在開發中(Xen/PPC)。同 X86 一樣,泛虛擬化的 Xen/IA-64 客戶機運行在 ring 1-3,通過 Event Channel 和 Hypercalls 同監控程序協同工作。同時 Xen/IA-64 支持虛擬塊設備(VBD)和虛擬網絡(VNIF)。

  在完全虛擬化支持方面,安騰架構也如同 X86 架構一樣存在虛擬化支持的漏洞。Intel® VT 技術引入了一個新的處理器模式——虛擬機模式,通過 PSR 寄存器中的 VM(Virtual Machine)位實現。當 VM 位為 0 時,處理器工作在 Host 模式,就如同沒有硬件虛擬化技術支持一樣。當 VM 位為 1 時,處理器工作在虛擬機模式,具有全部的 4 個ring。處于虛擬機模式時,不管處理器是否處于 ring 0 它對特權資源的訪問都會產生打斷(interruptions),進而使處理器進入 Host模式。如圖 7 所示,VMM 運行在 Host 模式,具有完全的特權級別,處理器被打斷后直接進入 VMM,從而實現對特權資源的虛擬化。不同于 X86,安騰架構有一層稱之為 PAL(Processor Abstraction Layer) 的處理器抽象層,將不同處理器實現之間的不同特點經過抽象提供一個統一的固件接口(firmwareinterface)。Intel® VT 技術同時實現了 PAL 的虛擬化支持。

  Xen 最新進展

  2005 年 12 月 5 日,XenSource 向外發布了 3.0 版本。Xen 3.0 支持 Intel® VT 技術、客戶機 SMP 及客戶機 CPU 熱插拔、動態移植、32 位/64 位和 PAE 客戶機支持、安騰架構支持、安全平臺、虛擬機的保存和恢復等等。動態移植技術可以使得一個虛擬機在不同的物理機器間移植而不需要關閉機器,同時不中斷虛擬機對外的服務。動態移植理論上可以使虛擬機器的服務永不間斷,在物理機器壽命到來之前移植到一個新機器上而繼續運行。虛擬機的保存和恢復可以為用戶提供機器級別的備份,而不需要關心用戶程序本身是否有備份功能,實現災難時候的恢復。

  預計 2006 年 9 月,XenSourcee 將向外發布他的第一個正式產品 XenEnterprise。XenEnterprise 基于 Xen 3.0.3,在這之前,Redhat 在他的 Fedora Core 4.0 和 Fedora Core 5.0 中已經集成了 Xen,Novell 在他的 SUSE Linux 10.1 和 SLES 10 中也已經集成了 Xen。同時 Redhat 計劃在他的下一個企業 Linux 即 RHEL 5.0 中集成 Xen。Xen 今天已經是一個事實上的開源虛擬化解決方案標準。

  Xen 虛擬機技術的開源特性、它的接近于原生系統的性能、永不停機的動態移植功能、以及同時對泛虛擬化客戶機操作系統和未經修改的操作系統的支持,吸引了包括華爾街分析師在內的廣泛關注。利用 Xen 進行服務器加固(Server Consolidation),搭建有虛擬機組成的網絡試驗和教學系統,利用虛擬機的保存/恢復(Save/Restore)實現服務器災難恢復(Disaster Recovery)等等,必將進一步提升國內企事業單位的計算機使用和管理水平,節約寶貴的設備購置經費和極大地提高系統的整體環境安全。

  [Reference]

  [1] Pratt, Ian; Fraser, Keir; Hand, Steve;Limpach, Christian; Warfield, Andrew;Magenheimer, Dan; Nakajima, Jun; Mallick,Asit; “Xen 3.0 and the Art ofVirtualization,” in Proceedings ofLinux Symposium, Volume Two, 2005.

  [2] Jeremy Sugerman, GaneshVenkitachalam and Beng-Hong Lim,“Virtualizing I/O Devices on VMwareWorkstation􏰂s Hosted Virtual MachineMonitor,” Proceedings of the 2001USENIX Annual Technical Conference,Boston, Massachusetts, June 2001.

  [3] Carl A. Waldspurger, “MemoryResource Management in VMware ESXServer,” Proceedings of the 5th symposiumon Operating systems design andimplementation (OSDI '02), December 2002.

  [4] A. Whitaker, M. Shaw, and S. Gribble,“Denali: Lightweight virtual machines fordistributed and networked applications,”Proceedings of the USENIX TechnicalConference, Monterey, CA, June 2002.

  [5] Uhlig, R.; Neiger, G.; Rodgers, D.; Santoni,A.L.; Martins, F.C.M.; Anderson, A.V.; Bennett,S.M.; Kagi, A.; Leung, F.H.; Smith, L.;”IntelVirtualization Technology,” IEEE ComputerVolume 38, Issue 5, pp. 48–56, May 2005.

  [6] Nakajima, Jun; Mallick, Asit; Pratt, Ian;Frser, Keir, ”X86-64 XenLinux: Architecture, Implementation, and Optimizations,” OttawaLinux Symposium, 2006.

  [7] 董耀祖,周正偉,,“基于X86體系架構的系統虛擬機技術發展現狀與應用”,計算機工程2006年第13期71頁。

  [8] http://www.linuxjournal.com/article/8909

5
1
 
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()