Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Data Exchange adalah layanan integrasi (juga dikenal sebagai pertukaran pasangan kunci-nilai atau KVP) yang dapat digunakan untuk berbagi informasi kecil antara komputer virtual (tamu) dan host Hyper-V. Informasi umum tentang komputer virtual dan host secara otomatis dibuat dan disimpan sebagai pasangan kunci-nilai. Anda juga dapat membuat pasangan Anda sendiri untuk berbagi data kustom.
Pasangan kunci-nilai terdiri dari "kunci" dan "nilai". Keduanya adalah string; tidak ada jenis data lain yang didukung. Saat pasangan kunci-nilai dibuat atau diubah, akan terlihat oleh tamu dan host. Data KVP melakukan perjalanan melalui Hyper-V VMbus dan tidak memerlukan konektivitas jaringan antara tamu dan host.
Setelah dibuat, pasangan kunci-nilai tetap ada sampai dihapus. Aplikasi apa pun yang membuat pasangan kunci-nilai harus menghapusnya saat tidak lagi diperlukan. Pasangan kunci-nilai berpindah dengan komputer virtual selama Migrasi Langsung.
Tamu Windows
Pada tamu Windows, data KVP disimpan di registri di bawah:
HKLM\SOFTWARE\Microsoft\Virtual Machine
Data diatur dalam sub-kunci ini:
- Virtual Machine\Auto – Data yang menjelaskan tamu. Dibuat oleh driver layanan integrasi setelah dimuat. Terlihat oleh host sebagai data intrinsik.
- Virtual Machine\External – Data yang didorong dari host ke mesin virtual oleh pengguna.
- Virtual Machine\Guest – Data yang dibuat pada guest. Terlihat oleh sistem host sebagai data non-intrinsik.
- Virtual Machine\Guest\Parameter – Data yang dikirimkan ke tamu dari host yang memberikan deskripsi tentang host.
Menambahkan nilai dari dalam mesin virtual semudah membuat nilai string baru di bawah HKLM\SOFTWARE\Microsoft\Virtual Machine\Guest. Anda harus menjadi administrator dalam lingkungan tamu untuk mengubah lokasi ini. Anda dapat menggunakan WMI (PowerShell atau alat lain) dari host atau komputer jarak jauh (dengan izin) untuk mengambil nilai.
Untuk informasi tentang batas ukuran registri, lihat artikel (warisan) Batas Ukuran Elemen Registri.
Tambahkan pasangan kunci-nilai baru pada sistem tamu
Dalam contoh ini, nilai Status diatur ke Ready:
$regPath = "HKLM:\SOFTWARE\Microsoft\Virtual Machine\Guest"
Set-ItemProperty -Path $regPath -Name "Status" -Value "Ready" -Type String
Anda dapat menggunakan sintaks yang sama untuk mengubah nilai.
Meminta pasangan kunci-nilai pada sistem tamu
Untuk meng-query nilai subkunci Eksternal (data yang didorong ke tamu oleh host):
$regPath = "HKLM:\SOFTWARE\Microsoft\Virtual Machine\External"
Get-ItemProperty -Path $regPath -Name "Name"
Tamu Linux
Linux tidak memiliki registri, sehingga item KVP disimpan dalam sistem file. Proses daemon, hv_kvp_daemon, harus berjalan untuk menangani pemrosesan. Untuk sebagian besar distribusi dengan Linux Integration Services (LIS) atau driver dalam kernel yang diinstal, daemon ini dimulai secara otomatis. Dalam beberapa kasus, langkah tambahan mungkin diperlukan untuk menginstal dan memulai daemon.
Layanan integrasi Linux menerapkan pertukaran data dengan kumpulan KVP. Kumpulan KVP adalah file yang disimpan di jalur tertentu. Ada empat file kumpulan:
/var/lib/hyperv/.kvp_pool_0
/var/lib/hyperv/.kvp_pool_1
/var/lib/hyperv/.kvp_pool_2
/var/lib/hyperv/.kvp_pool_3
Berkas kumpulan ini dikaitkan dengan sekumpulan kunci registri Windows berikut:
- Kumpulan 0:
Virtual Machine\External - Kumpulan 1:
Virtual Machine\Guest - Kumpulan 2:
Virtual Machine\Auto - Kumpulan 3:
Virtual Machine\Guest\Parameter
Nota
Untuk informasi selengkapnya tentang dukungan Linux KVP, lihat Linux dan FreeBSD Virtual Machines di Hyper-V.
Infrastruktur pasangan kunci-nilai mungkin tidak berfungsi dengan benar tanpa pembaruan perangkat lunak Linux. Hubungi vendor distribusi Anda untuk pembaruan jika Anda mengalami masalah.
Struktur kolam
Setiap file kumpulan berisi rekaman dengan struktur ini:
struct kvp_record
{
unsigned char key[ HV_KVP_EXCHANGE_MAK_KEY_SIZE ];
unsigned char value[ HV_KVP_EXCHANGE_MAX_VALUE_SIZE ];
};
Konstanta ukuran tersebut didefinisikan dalam hyperv.h (header kernel yang didistribusikan dengan sumber kernel Linux).
Membaca dan menampilkan nilai dari kumpulan 0
Sampel ini membaca nilai KVP dari kumpulan 0 dan menampilkannya.
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "../include/linux/hyperv.h"
typedef struct kvp_record
{
unsigned char key [HV_KVP_EXCHANGE_MAX_KEY_SIZE];
unsigned char value [HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
} KVP_RECORD;
KVP_RECORD myRecords[200];
void KVPAcquireLock(int fd)
{
struct flock fl = {F_RDLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLKW, &fl))
{
perror("fcntl lock");
exit (-10);
}
}
void KVPReleaseLock(int fd)
{
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLK, &fl))
{
perror("fcntl unlock");
exit (-20);
}
}
int main (int argc, char **argv)
{
char poolName[] = "/var/lib/hyperv/.kvp_pool_0";
int i;
int fd;
int bytesRead;
int numRecords;
fd = open(poolName, O_RDONLY);
if (-1 == fd)
{
printf("Error: Unable to open pool file %s\n", poolName);
exit (-30);
}
KVPAcquireLock(fd);
bytesRead = read(fd, myRecords, sizeof(myRecords));
KVPReleaseLock(fd);
numRecords = bytesRead / sizeof(struct kvp_record);
printf("Number of records : %d\n", numRecords);
for (i = 0; i < numRecords; i++)
{
printf(" Key : %s\n Value: %s\n\n", myRecords[i].key, myRecords[i].value);
}
close(fd);
return 0;
}
Membuat item KVP di kumpulan 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "../include/linux/hyperv.h"
typedef struct kvp_record
{
unsigned char key [HV_KVP_EXCHANGE_MAX_KEY_SIZE];
unsigned char value [HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
} KVP_RECORD;
void KVPAcquireWriteLock(int fd)
{
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLKW, &fl))
{
perror("fcntl lock");
exit (-10);
}
}
void KVPReleaseLock(int fd)
{
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLK, &fl))
{
perror("fcntl unlock");
exit (-20);
}
}
int main (int argc, char **argv)
{
char poolName[] = "/var/lib/hyperv/.kvp_pool_1";
int fd;
KVP_RECORD newKvp;
if (3 != argc)
{
printf("Usage: WritePool keyName valueString\n\n");
exit (-5);
}
fd = open(poolName, O_WRONLY);
if (-1 == fd)
{
printf("Error: Unable to open pool file %s\n", poolName);
exit (-30);
}
memset((void *)&newKvp, 0, sizeof(KVP_RECORD));
memcpy(newKvp.key, argv[1], strlen(argv[1]));
memcpy(newKvp.value, argv[2], strlen(argv[2]));
KVPAcquireWriteLock(fd);
write(fd, (void *)&newKvp, sizeof(KVP_RECORD));
KVPReleaseLock(fd);
close(fd);
return 0;
}
Menghapus item KVP dari kumpulan 1
Sampel ini menghapus item.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <uapi/linux/hyperv.h>
typedef struct kvp_record
{
unsigned char key [HV_KVP_EXCHANGE_MAX_KEY_SIZE];
unsigned char value [HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
} KVP_RECORD;
void KVPAcquireWriteLock(int fd)
{
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLKW, &fl))
{
perror("fcntl lock");
exit (-10);
}
}
void KVPReleaseLock(int fd)
{
struct flock fl = {F_UNLCK, SEEK_SET, 0, 0, 0};
fl.l_pid = getpid();
if (-1 == fcntl(fd, F_SETLK, &fl))
{
perror("fcntl unlock");
exit (-20);
}
}
int find_record_offset(int fd, char *key)
{
int bytesRead;
int offset = 0;
int retval = -1;
KVP_RECORD kvpRec;
while (1)
{
lseek(fd, offset, SEEK_SET);
bytesRead = read(fd, &kvpRec, sizeof(KVP_RECORD));
if (0 == bytesRead)
{
break;
}
if (0 == strcmp(key, (const char *) kvpRec.key))
{
retval = offset;
break;
}
offset += sizeof(KVP_RECORD);
}
return retval;
}
int main (int argc, char **argv)
{
char poolName[] = "/var/lib/hyperv/.kvp_pool_1";
int fd;
int exitVal = -1;
int bytesRead;
int bytesWritten;
int offset_to_delete;
int offset_last_record;
KVP_RECORD kvpRec;
if (2 != argc)
{
printf("Usage: WritePool keyName valueString\n\n");
exit (-5);
}
fd = open(poolName, O_RDWR, 0644);
if (-1 == fd)
{
printf("Error: Unable to open pool file %s\n", poolName);
exit (-10);
}
KVPAcquireWriteLock(fd);
offset_to_delete = find_record_offset(fd, argv[1]);
if (offset_to_delete < 0)
{
exitVal = -15;
goto cleanup2;
}
offset_last_record = lseek(fd, -sizeof(KVP_RECORD), SEEK_END);
if (offset_last_record < 0)
{
exitVal = -20;
goto cleanup2;
}
if (offset_last_record != offset_to_delete)
{
lseek(fd, offset_last_record, SEEK_SET);
bytesRead = read(fd, &kvpRec, sizeof(KVP_RECORD));
lseek(fd, offset_to_delete, SEEK_SET);
bytesWritten = write(fd, &kvpRec, sizeof(KVP_RECORD));
}
ftruncate(fd, offset_last_record);
exitVal = 0;
cleanup2:
KVPReleaseLock(fd);
cleanup1:
close(fd);
return exitVal;
}
Bekerja dengan pasangan kunci-nilai dari host menggunakan WMI
Contoh berikut menggunakan namespace WMI v2. Untuk WMI v1 (versi yang lebih lama), hapus \v2 segmen dari jalur namespace.
Nota
Jika Anda menggunakan Windows 8 atau Windows 8.1, instal Client Hyper-V untuk mendapatkan namespace.
Baca nilai dari host
Contoh ini mendapatkan nilai kunci Status dari VM bernama Vm1:
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName = 'Vm1'}
$vm.GetRelated("Msvm_KvpExchangeComponent").GuestExchangeItems | % { \
$GuestExchangeItemXml = ([XML]$_).SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Name']/VALUE[child::text() = 'Status']")
if ($GuestExchangeItemXml -ne $null)
{
$GuestExchangeItemXml.SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Data']/VALUE/child::text()" ).Value
}
}
Menambahkan atau mengubah pasangan kunci-nilai dari host
Untuk menambahkan pasangan kunci-nilai dari host, dapatkan instans dari kedua layanan manajemen dan VM, dan buat instans baru dari Msvm_KvpExchangeDataItem. Saat membuat instans baru, tentukan Name, , Datadan Source (harus 0). Kemudian hubungi AddKvpItems.
Kueri untuk pasangan kunci-nilai yang dibuat oleh host mirip dengan kueri tamu tetapi memerlukan hop asosiasi tambahan ke Msvm_KvpExchangeComponentSettingData. Memodifikasi dan menghapus nilai berfungsi dengan cara yang sama—tentukan nama kunci yang sama dan panggil metode Modify atau Remove yang sesuai.
Penting
Contoh di bawah ini menggunakan namespace v2. Jika Anda menggunakan Windows Server 2008 atau Windows Server 2008 R2, hapus segmen .\v2
Menambahkan pasangan kunci-nilai baru
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
$kvpDataItem = ([WMIClass][String]::Format("\\{0}\\{1}:{2}", \
$VmMgmt.ClassPath.Server, \
$VmMgmt.ClassPath.NamespacePath, \
"Msvm_KvpExchangeDataItem")).CreateInstance()
$kvpDataItem.Name = "Name"
$kvpDataItem.Data = "Data"
$kvpDataItem.Source = 0
$VmMgmt.AddKvpItems($Vm, $kvpDataItem.PSBase.GetText(1))
Mengkueri pasangan kunci-nilai pada host
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
($vm.GetRelated("Msvm_KvpExchangeComponent")[0] ).GetRelated("Msvm_KvpExchangeComponentSettingData").HostExchangeItems | % { \
$GuestExchangeItemXml = ([XML]$_).SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Name']/VALUE[child::text() = 'Name2']")
if ($GuestExchangeItemXml -ne $null)
{
$GuestExchangeItemXml.SelectSingleNode(\
"/INSTANCE/PROPERTY[@NAME='Data']/VALUE/child::text()" ).Value
}
}
Mengubah pasangan kunci-nilai
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
$kvpDataItem = ([WMIClass][String]::Format("\\{0}\\{1}:{2}", \
$VmMgmt.ClassPath.Server, \
$VmMgmt.ClassPath.NamespacePath, \
"Msvm_KvpExchangeDataItem")).CreateInstance()
$kvpDataItem.Name = "Name"
$kvpDataItem.Data = "Data2"
$kvpDataItem.Source = 0
$VmMgmt.ModifyKvpItems($Vm, $kvpDataItem.PSBase.GetText(1))
Menghapus pasangan kunci-nilai
$VmMgmt = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_VirtualSystemManagementService
$vm = Get-WmiObject -Namespace root\virtualization\v2 -Class \
Msvm_ComputerSystem -Filter {ElementName='VM1'}
$kvpDataItem = ([WMIClass][String]::Format("\\{0}\\{1}:{2}", \
$VmMgmt.ClassPath.Server, \
$VmMgmt.ClassPath.NamespacePath, \
"Msvm_KvpExchangeDataItem")).CreateInstance()
$kvpDataItem.Name = "Name"
$kvpDataItem.Data = [String]::Empty
$kvpDataItem.Source = 0
$VmMgmt.RemoveKvpItems($Vm, $kvpDataItem.PSBase.GetText(1))