Compartilhar via


Faça seus próprios serviços de integração

A partir da Atualização de Aniversário do Windows 10, qualquer pessoa pode fazer aplicativos que se comunicam entre o host Hyper-V e suas máquinas virtuais usando soquetes Hyper-V – um Soquete do Windows com uma nova família de endereços e ponto de extremidade especializado para direcionar máquinas virtuais. Toda a comunicação em Hyper-V soquetes é executada sem usar a rede e todos os dados permanecem na mesma memória física. Os aplicativos que usam soquetes Hyper-V são semelhantes aos serviços de integração do Hyper-V.

Este documento explica como criar um programa simples baseado em soquetes Hyper-V.

Sistema operacional host com suporte

  • Windows 10 e posterior
  • Windows Server 2016 e posterior

Sistema operacional convidado com suporte

Observação

Um convidado do Linux com suporte deve ter suporte ao kernel para:

CONFIG_VSOCKET=y
CONFIG_HYPERV_VSOCKETS=y

Funcionalidades e limitações

  • Dá suporte a ações do modo kernel ou do modo de usuário
  • Somente fluxo de dados
  • Nenhuma memória de bloco (não é a melhor para backup/vídeo)

Como começar

Requisitos:

  • Compilador C/C++. Se você não tiver um, faça check-out do Visual Studio Community
  • SDK do Windows – pré-instalado no Visual Studio 2015 com a Atualização 3 e posterior.
  • Um computador que executa um dos sistemas operacionais host especificados com pelo menos um computador vitual. -- isso é para testar seu aplicativo.

Nota: A API para soquetes Hyper-V tornou-se publicamente disponível na Atualização de Aniversário do Windows 10. Os aplicativos que usam HVSocket serão executados em qualquer host e convidado do Windows 10, mas só podem ser desenvolvidos com um SDK do Windows posterior ao build 14290.

Registrar um novo aplicativo

Para usar Hyper-V soquetes, o aplicativo deve ser registrado no registro do host do Hyper-V.

Ao registrar o serviço no registro, você obtém:

  • Gerenciamento do WMI para habilitar, desabilitar e listar serviços disponíveis
  • Permissão para se comunicar diretamente com máquinas virtuais

O PowerShell a seguir registrará um novo aplicativo chamado "Demonstração de Soquete HV". Isso deve ser executado como administrador. Instruções manuais abaixo.

$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

Localização e informações do Registro:

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

Neste local do Registro, você verá vários GUIDs. Esses são nossos serviços in-box.

Informações no registro por serviço:

  • Service GUID
    • ElementName (REG_SZ) -- este é o nome amigável do serviço

Para registrar seu próprio serviço, crie uma nova chave do Registro usando seu próprio GUID e seu nome amigável.

O nome amigável será associado ao novo aplicativo. Ele será exibido em contadores de desempenho e em outros locais em que um GUID não é apropriado.

A entrada do Registro tem esta aparência:

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

Observação

O GUID de Serviço para um convidado do Linux usa o protocolo VSOCK que aborda por meio de um svm_cid e svm_port em vez de guids. Para fazer a ponte dessa inconsistência com o Windows, o GUID conhecido é usado como o modelo de serviço no host que se traduz em uma porta no convidado. Para personalizar o GUID de Serviço, basta alterar o primeiro "000000000" para o número de porta desejado. Por exemplo: "000000ac9" é a 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
  */

Ponta: Para gerar um GUID no PowerShell e copiá-lo para a área de transferência, execute:

(New-Guid).Guid | clip.exe

Criar um soquete Hyper-V

No caso mais básico, definir um soquete requer uma família de endereços, um tipo de conexão e um protocolo.

Aqui está uma definição de soquete simples

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

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

Para um soquete Hyper-V:

  • Família de endereços – AF_HYPERV (Windows) ou AF_VSOCK (convidado do Linux)
  • tipo- SOCK_STREAM
  • protocolo – HV_PROTOCOL_RAW (Windows) ou 0 (convidado do Linux)

Aqui está um exemplo de declaração/instanciação:

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

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

Associar a um soquete Hyper-V

Associar um soquete a informações de conexão.

A definição de função é copiada abaixo para conviniência, leia mais sobre associação aqui.

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

Ao contrário do endereço do soquete (sockaddr) de uma família de endereços padrão do Protocolo de Internet (AF_INET) que consiste no endereço IP do computador host e um número de porta nesse host, o endereço do soquete usa AF_HYPERV a ID da máquina virtual e a ID do aplicativo definida acima para estabelecer uma conexão. Se a associação de um convidado AF_VSOCK do Linux usar o svm_cidsvm_port .

Como Hyper-V soquetes não dependem de uma pilha de rede, TCP/IP, DNS etc. o ponto de extremidade do soquete precisava de um formato não IP, não hostname, que ainda descreve de forma inequívoca a conexão.

Esta é a definição para o endereço do soquete de um soquete 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)];
};

Em vez de um IP ou nome de host, AF_HYPERV pontos de extremidade dependem muito de dois GUIDs:

  • ID da VM – essa é a ID exclusiva atribuída por VM. Uma ID de VM pode ser encontrada usando o snippet do PowerShell a seguir.

    (Get-VM -Name $VMName).Id
    
  • ID do serviço – GUID, descrito acima, com o qual o aplicativo é registrado no registro de host Hyper-V.

Há também um conjunto de curingas VMID disponíveis quando uma conexão não é com uma máquina virtual específica.

Curingas VMID

Nome GUID Description
HV_GUID_ZERO 00000000-0000-0000-0000-000000000000 Os ouvintes devem se associar a essa VmId para aceitar a conexão de todas as partições.
HV_GUID_WILDCARD 00000000-0000-0000-0000-000000000000 Os ouvintes devem se associar a essa VmId para aceitar a conexão de todas as partições.
HV_GUID_BROADCAST FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
HV_GUID_CHILDREN 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd Endereço curinga para crianças. Os ouvintes devem se associar a essa VmId para aceitar a conexão de seus filhos.
HV_GUID_LOOPBACK e0e16197-dd56-4a10-9195-5ee7a155a838 Endereço de loopback. Usar essa VmId conecta-se à mesma partição que o conector.
HV_GUID_PARENT a42e7cda-d03f-480c-9cc2-a4de20abb878 Endereço pai. Usar essa VmId conecta-se à partição pai do conector.*

* HV_GUID_PARENT O pai de uma máquina virtual é seu host. O pai de um contêiner é o host do contêiner. A conexão de um contêiner em execução em uma máquina virtual se conectará à VM que hospeda o contêiner. Ouvir essa VmId aceita a conexão de: (Dentro de contêineres): host de contêiner. (Dentro da VM: host de contêiner/ sem contêiner): host de VM. (Não dentro da VM: host de contêiner/ sem contêiner): não há suporte.

Comandos de soquete com suporte

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

Opções de soquete HvSocket

Nome Tipo Description
HVSOCKET_CONNECTED_SUSPEND ULONG Quando essa opção de soquete é definida como um soquete de valor diferente de zero, não se desconecte quando a máquina virtual está pausada.

Concluir a API do WinSock

referência doHyper-V Integration Services