学习xenstore

来源:互联网 发布:大连新港716火灾知乎 编辑:程序博客网 时间:2024/04/27 23:43

XenStore是一个类似于数据库的文件系统, 包含了domain间的共享信息. 有domain配置和状态信息.XenStore 提供了一种发现设备信息的简便方法. 它作为数据库在 /var/lib/xenstore/tdb, 在用户空间的 daemon 称为 "xenstored".这个逻辑文件树有三个主要的路径:

/vm - /vm/uuid 存储配置信息,例如虚拟CPU数和内存分配数.

/local/domain - 包含了正在运行的domain信息, 由domid标识.

/tool - 存储多种工具信息.

应用程序向这个数据库的 key 写信息, 配置驱动; 驱动在key上设置watch并对改变做出回应.

详细介绍请参考: http://wiki.xensource.com/xenwiki/XenStoreReference

访问xenstore

在guest kernel启动时xenstore经过start_info页而被访问到, 作为共享页的机器页帧号和event channel使用.Dom0工具使用UNIX domain socket /var/run/xenstored/socket 或 /var/run/xenstoed/socket_ro; Dom0工具使用proce接口/proc/xen/xenbus, 内核代码使用xenbus API.

命令

xenstore-read, xenstore-exists, xenstore-list, xenstor-, xsls, 用于和xenstored daemon数据库通信.
e.g. - #xenstore-list /local/domain/0

Domain 标识 

1) 通用唯一标识符(UUID)是标识domain的数字, 即使guest迁移也保持相同.

2) domain 标识(DOMID) 标识一个正在运行的实例, 当guest 迁移到另一台机器后DOMID改变.

什么是Xenbus

Xenbus是Xenstore的一个接口, 它也是在Xenstore之上写的设备驱动的连接协议. Xenbus是一个虚拟设备的mgmt bus. Xen PV "backend" 设备出现在xenbus上, 而且能被DomU使用PV "fronted"设备驱动访问到. 这些虚拟后端设备的状态由xenbus管理. 这些状态被存储到xenstore, 并且一直被Dom0和DomU的xenbus驱动程序监测.XenStore 指供了一个domain如何将前端设备与后端提供的服务联系起来的方法, (实际这部分是由XenBus承载的, 一种建立在XenStore顶层的协议). 后端与前端通信使用共享event channel 和 ring buffer通信. 所有规范的xen虚拟设备驱动在初始化时向XenBus注册自己. 这是通过传递xenbus_driver 结构体给
xenbus_register_devide()函数.

代码

以下代码创建两个可执行的, xenstore-read 和 xenstore-write 程序.

在一个Dom中运行xenstore-read - 从 /loca/doman/X/memory/target 读取Domx的memory/target值.依赖于你运行这个程序所在的Dom.

在一个Dom中运行xenstore-wirte - 写一个memory/target值到这个程序所运行的Dom.

 

view plaincopy to clipboardprint?
  1. // Example taken from wiki.xensource.com/xenwiki/XenStoreReference and some code added  
  2. //  
  3. // Compiled using  
  4. //        gcc -g xenstore.c -DREAD=1 -lxenstore -o xenstore-read  
  5. //        gcc -g xenstore.c -DWRITE=1 -lxenstore -o xenstore-write  
  6. //  
  7. // To change permissions on /local/domain/0, use  
  8. // xenstore-chod -r /local/domain/0 b  - for r and w  
  9. // xenstore-chod -r /local/domain/0 w  - for w  
  10. //  
  11. #include <sys/types.h>  
  12. #include <xs.h>  
  13. #include <stdio.h>  
  14. #include <string.h>  
  15. #include <malloc.h>  
  16. #include <sys/stat.h> // for lstat()  
  17. #include <stdlib.h> // for exit()  
  18. #define DOM0 0  
  19. #define DOMU 1  
  20. int dom = 999;  
  21. // This function checks if the app is in domU or dom0. The /proc/xen/capabilities  
  22. // contains the string "control_d" if the app is in a dom0  
  23. //  
  24. // /sys/hypervisor/type can be checked too, to see if we are running on a xen  
  25. // hyervisor  
  26. check_dom()  
  27. {  
  28.     FILE *file = NULL;  
  29.     char *filePath;  
  30.     struct stat linkAttrs;  
  31.     char buf[100] = "";  
  32.     filePath = "/proc/xen/capabilities";  
  33.     if ((lstat(filePath, &linkAttrs)) != 0) {  
  34.         perror("lstat");  
  35.         return;  
  36.     }  
  37.     if ((file = fopen("/proc/xen/capabilities""r")) == NULL) {  
  38.         perror("fopen");  
  39.         return;  
  40.     }     
  41.     if (!fgets(buf, sizeof(buf), file)) {  
  42.         // we are in DomU, since the buffer is empty  
  43.         printf("/n Surely in DOMU, since capabilities is empty");  
  44.         dom = DOMU;  
  45.         return;  
  46.     } else {  
  47.         // we are probably in Dom0  
  48.         printf("/n Probably in DOM0, since capabilities has some data");  
  49.         dom = DOM0;  
  50.     }  
  51.     // the following is in case they change the capabilities to have some  
  52.     // data in a DomU  
  53.     if ((strstr(buf, "control_d")) == NULL) {  
  54.         // we are in DomU  
  55.         printf("/n We are in DOMU");  
  56.         dom = DOMU;  
  57.     } else {  
  58.         // we are in Dom0  
  59.         printf("/n We are in DOM0");  
  60.         dom = DOM0;  
  61.     }  
  62.     return;  
  63. }  
  64. // xs_write is written outside a transaction. Else it does not work for me. Pass  
  65. // a XBT_NULL as a 2nd param to xs_write().  
  66. write_to_xenstore (struct xs_handle *xs, char* path) {  
  67.     char            somedata[8] = {"2200000"};  
  68.     xs_transaction_t    trans;  
  69.     bool            err;  
  70.     printf("/nWriting data %s of len %d to %s",  
  71.             somedata, strlen(somedata), path);  
  72.     // xs_write() -> xs_talkv()  
  73.     //    -> xs_write_all() -> write() - sys_write()  
  74.     //    -> xs_read_reply()  
  75.     err = xs_write(xs, XBT_NULL, path, &somedata[0],  
  76.                 strlen(somedata));  
  77.     if (!err) {  
  78.         printf("/n Could'nt write var in xenstore");  
  79.     }  
  80.     xs_daemon_close(xs);  
  81.     free(path);  
  82.     exit(0);  
  83. }  
  84. int main(int argc, char *argv[]) {  
  85.     struct xs_handle    *xs;    // handle to xenstore  
  86.     xs_transaction_t    trans;  
  87.     char            *path;  
  88.     int            fd;  
  89.     fd_set            set;  
  90.     bool            err;  
  91.     struct timeval tv = {.tv_sec = 0, .tv_usec = 0};  
  92.     char             **vec;  
  93.     unsigned int         num;  
  94.     char            *buf;  
  95.     char            **buf2;  
  96.     unsigned int        len, i;  
  97.     unsigned int        domid;  
  98.     // check if we are in Dom0 or DomU  
  99.     check_dom();  
  100.     // Connect to XenStore. From Dom0 we call xs_daemon_open,  
  101.     // and from DomU, we call xs_domain_open().   
  102.     // xs_daemon_open() -> get_handle(xs_daemon_socket()).  
  103.     // xs_daemon_socket()->xs_daemon_path() which returns  
  104.     // XENSTORED_PATH/socket. A get_handle() on the above path generates  
  105.     // a socket (PF_UNIX, SOCK_STREAM, 0) and connects to above socket.  
  106.     // For domU, connect to XenStore via xs_domain_open().  
  107.     // xs_domain_dev() returns path to /proc/xen/xenbus, and a  
  108.     // get_handle() on this returns a 'fd' to this file.  
  109.     if (dom == DOMU) {  
  110.         xs = xs_domain_open(); // DomU  
  111.         if (xs == NULL) error();  
  112.         buf = xs_read(xs, XBT_NULL, "domid", &len);  
  113.         if (!buf) {  
  114.             printf("/n Could not read domid");  
  115.             return;  
  116.         }  
  117.         domid = atoi(buf);  
  118.         printf("/n Retrieved Dom ID = %d/n", domid);  
  119.     } else {  
  120.         xs = xs_daemon_open();  // Dom0  
  121.         if (xs == NULL) error();  
  122.         trans = xs_transaction_start(xs);  
  123.         if (trans == 0) {  
  124.             printf("/n Could not start xaction with XS"); return;  
  125.         }  
  126.         // Get contents of a directory. Need to call free after use,  
  127.         // since the API mallocs memory  
  128.         buf2 = xs_directory(xs, trans, "/local/domain", &len);  
  129.         if (!buf2) {  
  130.             printf("/n Could not read XS dir /local/domain"); return;  
  131.         }  
  132.         xs_transaction_end(xs, trans, true);  
  133.         if (trans == 0) {  
  134.             printf("/n Could not end xaction with XS"); return;  
  135.         }  
  136.         printf("/n Len of Dir /local/domain is %d", len);  
  137.         printf("/n Dir Contents: ");  
  138.         for (i=0; i<len;i++) { printf("%s ", buf2[i]); }  
  139.         if (len == 1) {  
  140.             // we have only 1 Dom running, i.e. Dom0  
  141.             domid = atoi(buf2[0]);  
  142.         } else if (len == 2) {  
  143.             domid = atoi(buf2[1]);  
  144.         }  
  145.         // Set domid to 0, since Dom0 is always id 0  
  146.         domid = 0;  
  147.         printf("/n Setting Dom ID = %d/n", domid);  
  148.     }  
  149.     // Get the local Domain path in xenstore  
  150.     path = xs_get_domain_path(xs, domid);  
  151.     if (path == NULL) {  
  152.         printf("/n Dom Path in Xenstore not found");  
  153.         error(); return;  
  154.     }  
  155.     // xs_directory has an implicit root at /local/domain/<domid> in DomU  
  156.     // and thus need to just pass "memory/target" if we are running this  
  157.     // from a DomU to read the directory's contents  
  158.     if (dom == DOM0) {  
  159.         path = realloc(path, strlen(path) + strlen("/memory/target") + 1);  
  160.         if (path == NULL) {  
  161.             error(); return;  
  162.         }  
  163.         strcat(path, "/memory/target");  
  164.     } else {  
  165.         strcpy(path, "memory/target");  
  166.     }  
  167.          
  168.     printf("/nPath = %s", path);  
  169.      
  170.     // If we are doing a write to the xenstore, branch off here and  
  171.     // then exit from the program. Else for read, cary on, and do a  
  172.     // select() to wait for a change in watched values  
  173. #ifdef WRITE  
  174.     write_to_xenstore(xs, path);  
  175. #endif  
  176.     // Create a watch on the path  
  177.     err = xs_watch(xs, path, "mytoken");  
  178.     if (err == 0) {  
  179.         printf("/n Error in setting watch on mytoken in %s", path);  
  180.         error(); return;  
  181.     }  
  182.     // Watches are notified via a File Descriptor. We can POLL on this.  
  183.     fd = xs_fileno(xs);  
  184.     while (1) {  
  185.         FD_ZERO(&set);  
  186.         FD_SET(fd, &set);  
  187.         printf("!-");  
  188.         fflush(stdout);  
  189.         struct timeval tv = {.tv_sec = 5, .tv_usec = 0};  
  190.         if (select(fd+1, &set, NULL, NULL, &tv) > 0  
  191.             && FD_ISSET(fd, &set)) {  
  192.             printf("@");  
  193.             // This blocks is nothing is pending. Returns an array  
  194.             // containing path and token. Use Xs_WATCH_* to  
  195.             // access these elements. Call free after use.  
  196.             vec = xs_read_watch(xs, &num);  
  197.             if (!vec) {  
  198.                 printf("Error on watch firing");  
  199.                 error(); return;  
  200.             }  
  201.             // In our example code, the following will print out  
  202.             // /local/domain/0/memory/target|mytoken  
  203.             printf("/nvec contents: %s|%s/n", vec[XS_WATCH_PATH],  
  204.                     vec[XS_WATCH_TOKEN]);  
  205.             // Prepare a transacation to do a read  
  206.             trans = xs_transaction_start(xs);  
  207.             if (trans == 0) {  
  208.                 printf("/n Could'nt start xaction xenstore");  
  209.                 return;  
  210.             }  
  211.             buf = xs_read(xs, trans, vec[XS_WATCH_PATH], &len);  
  212.             if (!buf) {  
  213.                 printf("/n Could'nt read watch var in vec");  
  214.                 return;  
  215.             }  
  216.             xs_transaction_end(xs, trans, true);  
  217.             if (trans == 0) {  
  218.                 printf("/n Could not end xaction xenstore");  
  219.                 return;  
  220.             }  
  221.             if (buf) {  
  222.                 printf("/n buflen: %d, buf: %s", len, buf);  
  223.             }  
  224.         } // end of select  
  225.     } // end while(1)  
  226.     printf("/n");  
  227.     // cleanup  
  228.     close(fd);  
  229.     xs_daemon_close(xs);  
  230.     free(path);  
  231.     return;  
  232. }  

 

 

参考:

1] The Definitive Guide to the Xen Hypervisor David Chisnall

2] http://www.cs.uic.edu/~spopuri/minios.html

3] http://wiki.xensource.com/xenwiki/XenStoreReference

4] http://wiki.xensource.com/xenwiki/XenBus

5] http://lists.xensource.com/archives/html/xen-devel/2005-12/msg00151.html

6] http://wiki.xensource.com/xenwiki/XenBus

7] http://knol.google.com/k/learning-xenstore