Partager via


Créez vos propres services d’intégration

À compter de la mise à jour anniversaire Windows 10, tout le monde peut faire communiquer des applications qui communiquent entre l’hôte Hyper-V et ses machines virtuelles à l’aide de sockets Hyper-V, un socket Windows avec une nouvelle famille d’adresses et un point de terminaison spécialisé pour cibler des machines virtuelles. Toutes les communications sur les sockets Hyper-V s’exécutent sans utiliser de mise en réseau et toutes les données restent sur la même mémoire physique. Les applications utilisant des sockets Hyper-V sont similaires aux services d’intégration d’Hyper-V.

Ce document décrit la création d’un programme simple basé sur des sockets Hyper-V.

Système d’exploitation hôte pris en charge

  • Windows 10 et versions ultérieures
  • Windows Server 2016 et versions ultérieures

Système d’exploitation invité pris en charge

Remarque

Un invité Linux pris en charge doit prendre en charge le noyau pour :

CONFIG_VSOCKET=y
CONFIG_HYPERV_VSOCKETS=y

Fonctionnalités et limites

  • Prend en charge les actions du mode utilisateur ou du mode noyau
  • Flux de données uniquement
  • Aucune mémoire de bloc (ce qui n’est pas optimal pour la sauvegarde et la vidéo)

Mise en route

Conditions requises :

  • Compilateur C/C++. Si vous n’en avez pas, consultez Visual Studio Community
  • SDK Windows – préinstallé dans Visual Studio 2015 avec Mise à jour 3 et versions ultérieures.
  • Un ordinateur exécutant l’un des systèmes d’exploitation hôtes spécifiés avec au moins une machine virtuelle. -- il s’agit de tester votre application.

Remarque : L’API des sockets Hyper-V a été mise à la disposition du public dans Mise à jour anniversaire Windows 10. Les applications qui utilisent HVSocket s’exécutent sur n’importe quel hôte ou invité Windows 10, mais elles ne peuvent être développées qu’avec un SDK Windows ultérieur à la build 14290.

Inscrire une nouvelle application

Pour utiliser des sockets Hyper-V, l’application doit être inscrite dans le registre de l’hôte Hyper-V.

En inscrivant le service dans le registre, vous obtenez :

  • Une gestion WMI pour activer, désactiver et répertorier les services disponibles
  • Une autorisation de communiquer directement avec les machines virtuelles

La commande PowerShell suivante inscrit une nouvelle application appelée « HV Socket Demo ». Elle doit être exécutée en tant qu’administrateur. Instructions du manuel ci-dessous.

$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

Emplacement du Registre et informations :

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

Vous verrez plusieurs GUID dans cet emplacement du registre. Il s’agit des services que nous fournissons.

Informations dans le Registre pour chaque service :

  • Service GUID
    • ElementName (REG_SZ) – nom convivial du service

Pour inscrire votre propre service, créez une clé de Registre à l’aide de votre propre GUID et nom convivial.

Le nom convivial est associé à votre nouvelle application. Il apparaîtra dans les compteurs de performance et dans d’autres emplacements où un GUID n’est pas approprié.

L’entrée de registre ressemble à ceci :

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

Remarque

le GUID du Service d'un invité Linux utilise le protocole VSOCK qui adresse via un svm_cid et svm_port au lieu d’un GUIDS. Pour palier cette incohérence avec Windows, le GUID bien connu est utilisé comme modèle de service sur l’ordinateur hôte, ce qui se traduit par un port dans l’invité. Pour personnaliser votre GUID de service, il vous suffit de remplacer le premier « 00000000 » par le numéro de port de votre choix. Ex : « 00000ac9 » est le port 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
  */

Conseil : Pour générer un GUID dans PowerShell et le copier dans le Presse-papiers, exécutez :

(New-Guid).Guid | clip.exe

Créer un socket Hyper-V

Dans le cas le plus simple, la définition d’un socket exige une famille d’adresses, un type de connexion et un protocole.

Voici une définition de socket simple

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

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

Pour un socket Hyper-V :

  • Famille d’adresses : AF_HYPERV (Windows) ou AF_VSOCK (invité Linux)
  • type : SOCK_STREAM
  • Protocole : HV_PROTOCOL_RAW (Windows) ou 0 (invité Linux)

Voici un exemple de déclaration/d’instanciation :

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

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

Liaison à un socket Hyper-V

La fonction de liaison (bind) associe un socket à des informations de connexion.

La définition de fonction est copiée ci-dessous par souci de commodité. Pour en savoir plus sur la fonction bind, cliquez ici.

// 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);

Contrairement à l’adresse de socket (sockaddr) pour une famille d’adresses IP standard (AF_INET) qui se compose de l’adresse IP de la machine hôte et d’un numéro de port sur cet hôte, l’adresse de socket pour AF_HYPERV utilise les ID de la machine virtuelle et de l’application définis ci-dessus pour établir une connexion. En cas de liaison à partir d’un invité Linux, AF_VSOCK utilise svm_cid et svm_port.

Comme les sockets Hyper-V ne dépendent pas, entre autres, d’une pile réseau, de TCP/IP ni de DNS, le point de terminaison de socket exigeait un format autre qu’un nom d’hôte ou qu’une adresse IP qui décrive toujours sans ambiguïté la connexion.

Voici la définition d’une adresse de socket 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)];
};

À la place d’une adresse IP ou d’un nom d’hôte, les points de terminaison AF_HYPERV reposent largement sur deux GUID :

  • ID de machine virtuelle : il s’agit de l’ID unique affecté par machine virtuelle. L’ID d’une machine virtuelle est accessible à avec l’extrait de code PowerShell suivant.

    (Get-VM -Name $VMName).Id
    
  • ID de service : GUID, décrit ci-dessus, avec lequel l’application est inscrite dans le registre de l’hôte Hyper-V.

Il existe également un ensemble de caractères génériques VMID disponibles quand une connexion n’est pas propre à une machine virtuelle spécifique.

Caractères génériques VMID

Nom GUID Description
HV_GUID_ZERO 00000000-0000-0000-0000-000000000000 Les écouteurs doivent établir une liaison à ce VmId pour accepter la connexion de toutes les partitions.
HV_GUID_WILDCARD 00000000-0000-0000-0000-000000000000 Les écouteurs doivent établir une liaison à ce VmId pour accepter la connexion de toutes les partitions.
HV_GUID_BROADCAST FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
HV_GUID_CHILDREN 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd Adresse générique pour les enfants. Les écouteurs doivent établir une liaison à ce VmId pour accepter la connexion de ses enfants.
HV_GUID_LOOPBACK e0e16197-dd56-4a10-9195-5ee7a155a838 Adresse de bouclage. L’utilisation de ce VmId permet de se connecter à la même partition que le connecteur.
HV_GUID_PARENT a42e7cda-d03f-480c-9cc2-a4de20abb878 Adresse parente. L’utilisation de ce VmId permet de se connecter à la partition parente du connecteur.*

* HV_GUID_PARENT Le parent d’une machine virtuelle est son hôte. Le parent d’un conteneur est l’hôte du conteneur. Une connexion à partir d’un conteneur exécuté dans une machine virtuelle permet de se connecter à la machine virtuelle qui héberge le conteneur. L’écoute sur ce VmId accepte une connexion depuis : (Intérieur de conteneurs) : hôte de conteneur. (Intérieur de machine virtuelle : hôte de conteneur/aucun conteneur) : hôte de machine virtuelle. (Extérieur de machine virtuelle : hôte de conteneur/aucun conteneur) : aucune prise en charge.

Commandes de socket prises en charge

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

Options de socket HvSocket

Nom Type Description
HVSOCKET_CONNECTED_SUSPEND ULONG Quand cette option de socket est définie sur une valeur différente de zéro, les sockets ne se déconnectent pas quand la machine virtuelle est suspendue.

API WinSock complète

Informations de référence sur les services d’intégration Hyper-V