基于libvirt API监测xen初探

来源:互联网 发布:k30平板荷载试验算法 编辑:程序博客网 时间:2024/05/22 00:06


分类: Linux C 2008-05-25 12:53 5824人阅读 评论(9)收藏 举报

计算机体系结构课程布置了大作业,通过使用Xen的API或封装了其API的函数库,如libvirt进行编程,实现以下功能:

  1. 以命令行形式显示宿主机(Host OS)上正在运行的客户机(Guest OS)名称;
  2. 通过命令行形式显示指定客户机(Guest OS)的工作状态(显示其 CPU 利用率,和内存使用情况即可);

这个作业工程类似于Fedora等Linux系统中内置的xm管理程序,在这里仅简单的实现xm top的功能。我选用了Fedora Core 8作为Host OS。在其上,通过Xen安装另一Fedora Core 8作为Guest OS。利用libvirt提供的API实现显示Guest OS名称、显示其 CPU 利用率,和内存使用情况的功能。并与xm、virt-manager的运行结果做对比,验证正确性。

安装所需的软件包:

  • xen-3.1.2-2.fc8
  • libvirt-o.4.2-1.fc8
  • libvirt-devl-0.4.2-1.fc8

其中,xen为虚拟机,libvirt为运行库,libvirt-devl为代码运行库,供开发编译使用。具体版本视安装源与系统其他组件的依赖关系。

在我使用Xen安装Guest OS的过程中出现的一点小问题:在Fedora Core 8中发现默认提供的SELinux服务会对xen产生影响,估计可能是阻碍了某些信号量的传递,通过修改/etc/sysconfig/selinux,设置其中SELINUX=disabled将SElinux禁用。

通过virt-manager或virt-install安装Guest OS。设置为256m内存,4G硬盘空间,半虚拟化方式。

有关libvirt API的使用:

virConnectPtr virConnectOpenReadOnly (const char * name)在使用时首先应调用这个函数,获得hypervisor的链接nameURI of hypervisor,为NULL则代表本地链接Returns返回hypervisor的指针int virConnectListDomains (virConnectPtr conn, int * ids, int maxids) 获得hypervisor下所有域的ID connhypervisor链接指针ids存储每个域ID的数组maxids域数量的上限Returns域的数量virDomainPtr virDomainLookupByID (virConnectPtr conn, int id)由域的ID返回域的指针 connhypervisor链接指针id域的IDReturns返回域的指针int virDomainGetInfo (virDomainPtr domain, virDomainInfoPtr info)获得域的信息domain域的指针info指向存储域的信息的数据结构的指针Returns成功获取返回0,否则返回-1const char * virDomainGetName (virDomainPtr domain)得到域的名字domain域的指针Returns域的名字int virConnectClose (virConnectPtr conn)释放hyperbisor的连接,如果程序出线异常或错误应调用本函数终止连接connhypervisor的指针Returns成功释放返回0,否则返回-1int virDomainFree (virDomainPtr domain)释放域的指针,如果连接到域就要先调用这个函数释放域的链接,之后再释放hyperbisor的连接domain域的指针Returns成功释放返回0,否则返回-1

一个主要的数据结构:

struct virDomainInfounsigned charstate当前域的运行状态unsigned longmaxMem支持的最大内存unsigned longmemory使用的内存unsigned shortnrVirtCpu虚拟CPU数量unsigned long longcpuTime虚拟CPU运行时间

我的设计思路是,利用virConnectOpenReadOnly()获取链接,通过virConnectListDomains()得到当前活跃的域的ID。对于每一个ID利用virDomainLookupByID()得到指向其域的指针。调用virDomainGetInfo()获得当前域的内存、CPU运行时间等信息。当前域的名称由virDomainGetName()获得。

CPU占用率的计算方法为:在myxm中两次调用virDomainGetInfo()获取时间段开始前和结束后的虚拟CPU运行时间,二者差值可知虚拟CPU的运行时间。间隔时间段用sleep()实现。在sleep()前后用gettimeofday()取得真实的时间差。该时间段内CPU运行时间与真实时间的比值即为这段时间内的CPU占用率。

编译时gcc增加-lvirt参数,用于包含libvirt-devl库。

[csharp] view plaincopy
  1. <pre class="csharp" name="code">/** 
  2.  * Project: myxm 
  3.  * Version: 0.2 
  4.  * Abstract: A simple xen monitor 
  5.  * Author: Gu Xiangnan 
  6.  * Date: 2008-05-25 
  7.  */  
  8.  
  9. #include <stdlib.h></stdlib.h>  
  10. #include <stdio.h></stdio.h>  
  11. #include <libvirt libvirt.h=""></libvirt>  
  12.  
  13. #define MAXID 50  
  14.   
  15. /* the data structure of time */  
  16. typedef struct timeInfo  
  17. {  
  18.     long long cpu_time;  
  19.     struct timeval real_time;  
  20. } timeInfoNode;  
  21.   
  22. /* the hypervisor connection */  
  23. static virConnectPtr conn = NULL;  
  24.   
  25. /* release the connect of hypervisor */  
  26. void closeConn()  
  27. {  
  28.     if (conn != NULL)  
  29.         virConnectClose(conn);  
  30. }  
  31.   
  32. /* release the domain pointer */  
  33. void freeDom(virDomainPtr dom)  
  34. {  
  35.     if (dom != NULL)  
  36.         virDomainFree(dom);  
  37. }  
  38.   
  39. /* get the start time of each domain */  
  40. void getTimeInfo(int id, timeInfoNode * infos)  
  41. {  
  42.     virDomainPtr dom = NULL;  
  43.     virDomainInfo info;  
  44.     int ret;  
  45.   
  46.     /* Find the domain of the given id */  
  47.     dom = virDomainLookupByID(conn, id);  
  48.     if (dom == NULL)  
  49.     {  
  50.         fprintf(stderr, "Failed to find Domain %d/n", id);  
  51.         freeDom(dom);  
  52.         closeConn();  
  53.     }  
  54.   
  55.     /* Get the information of the domain */  
  56.     ret = virDomainGetInfo(dom, &info);  
  57.     if (ret < 0)  
  58.     {  
  59.         fprintf(stderr, "Failed to get information for Domain %d/n", id);  
  60.         freeDom(dom);  
  61.         closeConn();  
  62.     }  
  63.   
  64.     /* get the start of realTime*/  
  65.     if (gettimeofday(&(infos->real_time), NULL) ==  - 1)  
  66.     {  
  67.         fprintf(stderr, "Failed to get start time/n");  
  68.             return;  
  69.     }  
  70.   
  71.     /* get the start of CPUTime*/  
  72.     infos->cpu_time = info.cpuTime; /* nanosecond */  
  73.   
  74.     freeDom(dom);  
  75. }  
  76.   
  77. void getDomainInfo(int id, timeInfoNode infos)  
  78. {  
  79.     virDomainPtr dom = NULL;  
  80.     virDomainInfo info;  
  81.     int ret;  
  82.     struct timeval realTime;  
  83.     int cpu_diff, real_diff;  
  84.     float usage;  
  85.   
  86.     /* Find the domain of the given id */  
  87.     dom = virDomainLookupByID(conn, id);  
  88.     if (dom == NULL)  
  89.     {  
  90.         fprintf(stderr, "Failed to find Domain %d/n", id);  
  91.         freeDom(dom);  
  92.         closeConn();  
  93.     }   
  94.   
  95.     /* Get the information of the domain */  
  96.     ret = virDomainGetInfo(dom, &info);  
  97.     if (ret < 0)  
  98.     {  
  99.         fprintf(stderr, "Failed to get information for Domain %d/n", id);  
  100.         freeDom(dom);  
  101.         closeConn();  
  102.     }  
  103.   
  104.     /* get the end of realTime*/  
  105.     if (gettimeofday(&realTime, NULL) ==  - 1)  
  106.     {  
  107.         fprintf(stderr, "Failed to get start time/n");  
  108.         return;  
  109.     }  
  110.   
  111.     /* calculate the usage of cpu */  
  112.     cpu_diff = (info.cpuTime - infos.cpu_time) / 10000;  
  113.     real_diff = 1000 *(realTime.tv_sec - infos.real_time.tv_sec) +   
  114.         (realTime.tv_usec - infos.real_time.tv_usec);  
  115.     usage = cpu_diff / (float)(real_diff);  
  116.   
  117.     /* print the results */  
  118.     printf("%d/t%.3f%/t%lu/t%lu/t%hu/t%0X/t%s/n", id, usage, info.memory / 1024,  
  119.         info.maxMem / 1024, info.nrVirtCpu, info.state, virDomainGetName(dom));  
  120.   
  121.     freeDom(dom);  
  122. }  
  123.   
  124. int main()  
  125. {  
  126.     int idCount;  
  127.     int i;  
  128.     int id;  
  129.     int ids[MAXID];  
  130.     timeInfoNode timeInfos[MAXID];  
  131.   
  132.     printf("--------------------------------------------------------/n");  
  133.     printf("             XEN Domain Monitor Version 0.2/n");  
  134.     printf("             Build by Gu Xiangnan 35060514/n");  
  135.     printf("--------------------------------------------------------/n");  
  136.   
  137.     /* NULL means connect to local Xen hypervisor */  
  138.     conn = virConnectOpenReadOnly(NULL);  
  139.     if (conn == NULL)  
  140.     {  
  141.         fprintf(stderr, "Failed to connect to hypervisor/n");  
  142.         closeConn();  
  143.         return 0;  
  144.     }  
  145.   
  146.     /* get the count of IDs and save these ID into ids[] */  
  147.     idCount = virConnectListDomains(conn, &ids[0], MAXID);  
  148.     if (idCount < 0)  
  149.     {  
  150.         fprintf(stderr, "Failed to list the domains/n");  
  151.         closeConn();  
  152.         return 0;  
  153.     }  
  154.   
  155.     printf("Domain Totals: %d/n", idCount);  
  156.     printf("ID/tCPU/tMEM/tMaxMEM/tVCPUs/tState/tNAME/n");  
  157.   
  158.     /* loop get the CPUtime info by IDs */  
  159.     for (i = 0; i < idCount; i++)  
  160.     {  
  161.         id = ids[i];  
  162.         getTimeInfo(id, &(timeInfos[i]));  
  163.     }  
  164.   
  165.     sleep(1);  
  166.   
  167.     /* loop print the domain info and calculate the usage of cpus*/  
  168.     for (i = 0; i < idCount; i++)  
  169.     {  
  170.         id = ids[i];  
  171.         getDomainInfo(id, timeInfos[i]);  
  172.     }  
  173.   
  174.     printf("--------------------------------------------------------/n");  
  175.     closeConn();  
  176.     return 0;  
  177. }  
  178. </pre>  

运行结果:

 

可以对比一下vmm与xm top,验证实现的正确性:

 


原创粉丝点击