Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Data Exchange är en integrationstjänst (även kallat nyckel/värde-parutbyte eller KVP) som kan användas för att dela små mängder information mellan en virtuell dator (gäst) och dess Hyper-V värd. Allmän information om den virtuella datorn och värden skapas automatiskt och lagras som nyckel/värde-par. Du kan också skapa egna par för att dela anpassade data.
Nyckel/värde-par består av en "nyckel" och ett "värde". Båda är strängar. inga andra datatyper stöds. När ett nyckel/värde-par skapas eller ändras blir det synligt för både gästen och värden. KVP-data överförs via Hyper-V VMbus och kräver ingen nätverksanslutning mellan gästen och värden.
När de har skapats finns nyckel/värde-par kvar tills de tas bort. Alla program som skapar nyckel/värde-par bör ta bort dem när de inte längre behövs. Nyckel/värde-par flyttas med den virtuella datorn under direktmigrering.
Windows-gäster
På Windows-gäster lagras KVP-data i registret under:
HKLM\SOFTWARE\Microsoft\Virtual Machine
Data ordnas i dessa undernycklar:
- Virtuell dator\Auto – Data som beskriver gästen. Skapas av integrationstjänstens drivrutiner när de laddas. Synlig för värdsystemet som inneboende data.
- Virtuell maskin\Extern – Data som överförs till gästsystemet från värdsystemet av en användare.
- Virtuell dator\Gästsystem – Data som skapats i gästsystemet. Synlig för datorvärden som icke-intrinsisk data.
- Virtual Machine\Guest\Parameter – Data som skickas till gästen från värden som beskriver värden.
Att lägga till värden inifrån gästen är lika enkelt som att skapa ett nytt strängvärde under HKLM\SOFTWARE\Microsoft\Virtual Machine\Guest. Du måste vara administratör på gästoperativsystemet för att kunna ändra den här platsen. Du kan använda WMI (PowerShell eller andra verktyg) från din dator eller en fjärrdator (med behörigheter) för att hämta värdet.
Information om storleksbegränsningar för register finns i artikeln om storleksbegränsningar för registerelement.
Lägg till ett nytt nyckel/värde-par i gästmiljön
I det här exemplet anges värdet för Status till Ready:
$regPath = "HKLM:\SOFTWARE\Microsoft\Virtual Machine\Guest"
Set-ItemProperty -Path $regPath -Name "Status" -Value "Ready" -Type String
Du kan använda samma syntax för att ändra värdet.
Sök nyckel-värde-par i gästen
Så här frågar du efter värdet av undernyckeln Extern (data som skickas till gästen från värdsystemet):
$regPath = "HKLM:\SOFTWARE\Microsoft\Virtual Machine\External"
Get-ItemProperty -Path $regPath -Name "Name"
Linux-gäster
Linux har inget register, så KVP-objekt lagras i filsystemet. En daemonprocess, hv_kvp_daemon, måste köras för att hantera bearbetningen. För de flesta distributioner med Linux Integration Services (LIS) eller in-kernel-drivrutiner installerade startar den här daemonen automatiskt. I vissa fall kan det krävas extra steg för att installera och starta daemon.
Linux-integreringstjänsterna implementerar datautbyte med KVP-pooler. En KVP-pool är en fil som lagras i en specifik sökväg. Det finns fyra filer för poolen:
/var/lib/hyperv/.kvp_pool_0
/var/lib/hyperv/.kvp_pool_1
/var/lib/hyperv/.kvp_pool_2
/var/lib/hyperv/.kvp_pool_3
Dessa poolfiler mappas till följande Windows-registernyckeluppsättningar:
- Pool 0:
Virtual Machine\External - Pool 1:
Virtual Machine\Guest - Pool 2:
Virtual Machine\Auto - Pool 3:
Virtual Machine\Guest\Parameter
Anmärkning
Mer information om stöd för Linux KVP finns i Virtuella Linux- och FreeBSD-datorer på Hyper-V.
Nyckel/värde-parinfrastrukturen kanske inte fungerar korrekt utan en Linux-programuppdatering. Kontakta distributionsleverantören för en uppdatering om du stöter på problem.
Poolstruktur
Varje poolfil innehåller poster med den här strukturen:
struct kvp_record
{
unsigned char key[ HV_KVP_EXCHANGE_MAK_KEY_SIZE ];
unsigned char value[ HV_KVP_EXCHANGE_MAX_VALUE_SIZE ];
};
Dessa storlekskonstanter definieras i hyperv.h (en kernelrubrik som distribueras med Linux-kernelkällorna).
Läsa och visa värden från pool 0
Det här exemplet läser KVP-värden från pool 0 och visar dem.
```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;
}
Skapa ett KVP-objekt i pool 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;
}
Ta bort ett KVP-objekt från pool 1
Det här exemplet tar bort ett objekt.
#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;
}
Arbeta med nyckel/värde-par från värden med hjälp av WMI
I följande exempel används namnområdet WMI v2. För WMI v1 (äldre versioner) tar du \v2 bort segmentet från namnområdessökvägen.
Anmärkning
Om du använder Windows 8 eller Windows 8.1 installerar du Client Hyper-V för att hämta namnrymderna.
Läs värdet från värdenheten
Det här exemplet hämtar värdet för nyckeln Status från en virtuell dator med namnet 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
}
}
Lägga till eller ändra nyckel/värde-par från värden
Om du vill lägga till ett nyckel/värde-par från värden hämtar du instanser av både hanteringstjänsten och den virtuella datorn och skapar en ny instans av Msvm_KvpExchangeDataItem. När du skapar den nya instansen, Name anger du Data och Source (måste vara 0). Sedan anropa AddKvpItems.
Att fråga efter nyckel/värde-par som skapats av värd liknar gästförfrågningar men kräver ytterligare ett associationshopp till Msvm_KvpExchangeComponentSettingData. Att ändra och ta bort värden fungerar på samma sätt – ange samma nyckelnamn och anropa lämplig Modify metod eller Remove metod.
Viktigt!
I exemplen nedan används namnområdet v2. Om du använder Windows Server 2008 eller Windows Server 2008 R2 tar du bort \v2 segmentet.
Lägga till ett nytt nyckel/värde-par
$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))
Sök nyckel/värde-par på hosten
$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
}
}
Ändra ett nyckel/värde-par
$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))
Ta bort ett nyckel/värde-par
$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))