Share via


Creare servizi di integrazione personalizzati

A partire dall'Aggiornamento dell'anniversario di Windows 10, chiunque può creare applicazioni che comunicano con l'host Hyper-V e le relative macchine virtuali utilizzando socket di Hyper-V, un socket di Windows con una nuova famiglia di indirizzi ed endpoint specializzato per la selezione della destinazione delle macchine virtuali. Tutte le comunicazioni sui socket di Hyper-V vengono eseguite senza l'utilizzo di rete e tutti i dati rimangono nella stessa memoria fisica. Le applicazioni che utilizzano i socket di Hyper-V sono simili a servizi di integrazione di Hyper-V.

In questo documento viene illustrato come creare un programma semplice basato su socket di Hyper-V.

Sistemi operativi host supportati

  • Windows 10 e versioni successive
  • Windows Server 2016 e versioni successive

Sistemi operativi guest supportati

Nota: Un guest Linux supportato deve disporre del supporto del kernel per:

CONFIG_VSOCKET=y
CONFIG_HYPERV_VSOCKETS=y

Funzionalità e limitazioni

  • Supporta azioni in modalità utente o in modalità kernel
  • Solo flusso di dati
  • Nessuna memoria di blocco (non ideale per backup e video)

Introduzione

Requisiti:

  • Un compilatore C/++. Se non è disponibile un compilatore, fare riferimento alla community di Visual Studio
  • Windows 10 SDK: preinstallato in Visual Studio 2015 con Update 3 e versioni successive.
  • Un computer che esegue uno dei sistemi operativi host sopra elencati con almeno una macchina virtuale. Utilizzato per il test dell'applicazione.

Nota: L'API per i socket Hyper-V è diventata pubblicamente disponibile in Windows 10 Update dell'anniversario. Le applicazioni che usano HVSocket verranno eseguite in qualsiasi host e guest Windows 10, ma possono essere sviluppate solo con Windows SDK più tardi della build 14290.

Registrare una nuova applicazione

Per usare i socket di Hyper-V, l'applicazione deve essere registrata nel registro di sistema dell'host Hyper-V.

Con la registrazione del servizio nel registro di sistema, è possibile ottenere:

  • Gestione WMI per l’abilitazione, la disabilitazione e la visualizzazione dell’elenco dei servizi disponibili
  • Autorizzazioni necessarie per la comunicazione diretta con le macchine virtuali

Il comando PowerShell seguente registra una nuova applicazione denominata "HV Socket Demo". Eseguire il comando come amministratore. Le istruzioni per l’esecuzione manuale sono fornite di seguito.

$friendlyName = "HV Socket Demo"

# Create a new random GUID.  Add it to the services list
$service = New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices" -Name ((New-Guid).Guid)

# Set a friendly name
$service.SetValue("ElementName", $friendlyName)

# Copy GUID to clipboard for later use
$service.PSChildName | clip.exe

Posizione e informazioni del Registro di sistema:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices\

In questo percorso del Registro di sistema è possibile visualizzare diversi GUID. Questi sono i servizi inclusi.

Informazioni del registro di sistema per ogni servizio:

  • Service GUID
    • ElementName (REG_SZ): nome descrittivo del servizio

Per registrare il proprio servizio, creare una nuova chiave del registro di sistema usando il proprio GUID e il nome descrittivo.

Il nome descrittivo viene associato alla nuova applicazione. Viene visualizzato nei contatori delle prestazioni e in altre posizioni in cui un GUID non è appropriato.

La voce del registro di sistema apparirà come segue:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices\
    999E53D4-3D5C-4C3E-8779-BED06EC056E1\
        ElementName    REG_SZ    VM Session Service
    YourGUID\
        ElementName    REG_SZ    Your Service Friendly Name

Nota: Il GUID del servizio per un guest Linux usa il protocollo VSOCK che indirizza tramite un svm_cid guid e svm_port anziché un guid. Per colmare questa incoerenza con Windows, il GUID noto viene usato come modello di servizio nell'host che si traduce in una porta nel guest. Per personalizzare il GUID del servizio, è sufficiente modificare il primo "0000000" al numero di porta desiderato. Ad esempio: "00000ac9" è la porta 2761.

// Hyper-V Socket Linux guest VSOCK template GUID
struct __declspec(uuid("00000000-facb-11e6-bd58-64006a7986d3")) VSockTemplate{};

 /*
  * GUID example = __uuidof(VSockTemplate);
  * example.Data1 = 2761; // 0x00000AC9
  */

Mancia: Per generare un GUID in PowerShell e copiarlo negli Appunti, eseguire:

(New-Guid).Guid | clip.exe

Creare un socket di Hyper-V

Nel caso più semplice, la definizione di un socket richiede una famiglia di indirizzi, il tipo di connessione e il protocollo.

Ecco una semplice definizione di socket

// Windows
SOCKET WSAAPI socket(
  _In_ int af,
  _In_ int type,
  _In_ int protocol
);

// Linux guest
int socket(int domain, int type, int protocol);

Per un socket di Hyper-V:

  • Famiglia di indirizzi - AF_HYPERV (Windows) o AF_VSOCK (guest Linux)
  • tipo - SOCK_STREAM
  • protocollo - HV_PROTOCOL_RAW (Windows) o 0 (guest Linux)

Ecco una dichiarazione/creazione di istanza di esempio:

// Windows
SOCKET sock = socket(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW);

// Linux guest
int sock = socket(AF_VSOCK, SOCK_STREAM, 0);

Associare un socket di Hyper-V

Il binding associa il socket alle informazioni di connessione.

La definizione della funzione è riportata di seguito per praticità. Per altre informazioni, fare clic qui.

// Windows
int bind(
  _In_ SOCKET                s,
  _In_ const struct sockaddr *name,
  _In_ int                   namelen
);

// Linux guest
int bind(int sockfd, const struct sockaddr *addr,
         socklen_t addrlen);

A differenza dell'indirizzo del socket (sockaddr) per una famiglia di indirizzi IP (Internet Protocol) standard (AF_INET) che include l'indirizzo IP del computer host e un numero di porta dell'host, l'indirizzo del socket per AF_HYPERV usa l'ID della macchina virtuale e l'ID applicazione definiti in precedenza per stabilire una connessione. Se l'associazione svm_cid da un guest AF_VSOCK Linux usa e .svm_port

Poiché i socket di Hyper-V non dipendono da un stack di rete TCP/IP, DNS ed endpoint del socket hanno richiesto un formato non IP e non nome host che descrive chiaramente la connessione.

Di seguito è riportata la definizione dell'indirizzo di un socket di Hyper-V:

// Windows
struct SOCKADDR_HV
{
     ADDRESS_FAMILY Family;
     USHORT Reserved;
     GUID VmId;
     GUID ServiceId;
};

// Linux guest
// See include/uapi/linux/vm_sockets.h for more information.
struct sockaddr_vm {
    __kernel_sa_family_t svm_family;
    unsigned short svm_reserved1;
    unsigned int svm_port;
    unsigned int svm_cid;
    unsigned char svm_zero[sizeof(struct sockaddr) -
                   sizeof(sa_family_t) -
                   sizeof(unsigned short) -
                   sizeof(unsigned int) - sizeof(unsigned int)];
};

Invece che su un indirizzo IP o nome host, gli endpoint AF_HYPERV si basano su due GUID:

  • ID macchina virtuale: ID univoco assegnato a ciascuna macchina virtuale. È possibile determinare l'ID di una macchina virtuale usando il seguente frammento di PowerShell.
    (Get-VM -Name $VMName).Id
    
  • ID servizio: GUID, descritto sopra, con cui viene registrata l'applicazione nel Registro di sistema dell'host Hyper-V.

Quando non viene stabilita una connessione a una macchina virtuale specifica è disponibile anche un set di caratteri jolly dell’ID della macchina virtuale.

Caratteri jolly dell’ID della macchina virtuale

Nome GUID Descrizione
HV_GUID_ZERO 00000000-0000-0000-0000-000000000000 Per accettare la connessione da tutte le partizioni, i listener devono essere associati a questo ID di macchina virtuale.
HV_GUID_WILDCARD 00000000-0000-0000-0000-000000000000 Per accettare la connessione da tutte le partizioni, i listener devono essere associati a questo ID di macchina virtuale.
HV_GUID_BROADCAST FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
HV_GUID_CHILDREN 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd Indirizzo con caratteri jolly per gli elementi figlio. Per accettare la connessione dagli elementi figlio, i listener devono essere associati a questo ID di macchina virtuale.
HV_GUID_LOOPBACK e0e16197-dd56-4a10-9195-5ee7a155a838 Indirizzo di loopback. Usando questo ID di macchina virtuale viene stabilita una connessione alla stessa partizione del connettore.
HV_GUID_PARENT a42e7cda-d03f-480c-9cc2-a4de20abb878 Indirizzo padre. Usando questo ID di macchina virtuale viene stabilita una connessione alla partizione padre del connettore.*

* HV_GUID_PARENT L'elemento padre di una macchina virtuale è il relativo host. L'elemento padre di un contenitore è l'host del contenitore. La connessione da un contenitore in esecuzione in una macchina virtuale connette alla macchina virtuale che ospita il contenitore. L'ascolto su questo VmId accetta la connessione da: (contenitori interni): host contenitore. (All’interno della macchina virtuale: host contenitore/nessun contenitore): host della macchina virtuale. (Non all’interno della macchina virtuale: host contenitore/nessun contenitore): non supportato.

Comandi dei socket supportati

Socket() Bind() Connect() Send() Listen() Accept()

Opzioni socket HvSocket

Nome Tipo Descrizione
HVSOCKET_CONNECTED_SUSPEND ULONG Quando questa opzione socket è impostata su un socket senza valore zero, non si disconnette quando la macchina virtuale viene sospesa.

API WinSock complete

Riferimento per i servizi di integrazione Hyper-V