Partilhar via


Crie os seus próprios serviços de integração

A partir da Atualização de Aniversário do Windows 10, qualquer pessoa pode criar aplicativos que se comunicam entre o host Hyper-V e suas máquinas virtuais usando soquetes Hyper-V -- um Windows Socket com uma nova família de endereços e ponto de extremidade especializado para direcionar máquinas virtuais. Toda a comunicação através de Hyper-V sockets é executada sem utilizar 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 descreve a criação de um programa simples construído em Hyper-V soquetes.

SO host suportado

  • Windows 10 e posterior
  • Windows Server 2016 e posterior

SO convidado suportado

Observação

Um convidado Linux suportado deve ter suporte de kernel para:

CONFIG_VSOCKET=y
CONFIG_HYPERV_VSOCKETS=y

Capacidades e limitações

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

Como Começar

Requisitos:

  • Compilador C/C++. Se você não tiver um, confira a Comunidade do Visual Studio
  • SDK do Windows -- pré-instalado no Visual Studio 2015 com Atualização 3 e posterior.
  • Um computador executando um dos sistemas operacionais host especificados com pelo menos uma máquina vitual. -- isto é para testar a sua aplicação.

Observação: A API para soquetes de Hyper-V tornou-se disponível publicamente 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 à compilação 14290.

Registar uma nova candidatura

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

Ao registar o serviço no registo, obtém:

  • Gerenciamento 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 "HV Socket Demo". 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 registo:

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

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

Informações no registo 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 de registro usando seu próprio GUID e nome amigável.

O nome amigável será associado ao seu novo aplicativo. Ele aparecerá em contadores de desempenho e outros locais onde 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 Linux usa o protocolo VSOCK que aborda através de um svm_cid e svm_port em vez de um guids. Para preencher essa 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 seu GUID de serviço, basta alterar o primeiro "00000000" para o número de porta desejado. Ex: "00000ac9" é 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
  */

Dica: 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, tipo de conexão e 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 Linux)
  • tipo - SOCK_STREAM
  • protocolo - HV_PROTOCOL_RAW (Windows) ou 0 (convidado 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);

Ligar a um soquete Hyper-V

Bind associa um soquete às informações de conexão.

A definição da função é copiada abaixo para conviniência, leia mais sobre bind 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);

Em contraste com o endereço de soquete (sockaddr) para uma família de endereços de protocolo Internet padrão (AF_INET) que consiste no endereço IP da máquina host e um número de porta nesse host, o endereço de soquete para AF_HYPERV usa o ID da máquina virtual e o ID do aplicativo definido acima para estabelecer uma conexão. Se a vinculação de um convidado AF_VSOCK Linux usar o svm_cid e o svm_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 de nome de host, que ainda descreve inequivocamente a conexão.

Aqui está a definição para o endereço de soquete de um soquete de 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 fortemente de dois GUIDs:

  • ID da VM – esta é a ID exclusiva atribuída por VM. A ID de uma VM pode ser encontrada usando o seguinte trecho do PowerShell.

    (Get-VM -Name $VMName).Id
    
  • ID de serviço – GUID, descrito acima, com o qual o aplicativo está registrado no registro do 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 vincular a esse VmId para aceitar conexão de todas as partições.
HV_GUID_WILDCARD 00000000-0000-0000-0000-000000000000 Os ouvintes devem se vincular a esse VmId para aceitar 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 vincular a esse VmId para aceitar a conexão de seus filhos.
HV_GUID_LOOPBACK E0E16197-DD56-4A10-9195-5EE7A155A838 Endereço de loopback. Usando este VmId se conecta à mesma partição que o conector.
HV_GUID_PARENT A42E7CDA-D03F-480C-9CC2-A4DE20ABB878 Endereço dos pais. Usando este VmId se conecta à 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 a partir de um contêiner em execução em uma máquina virtual se conectará à VM que hospeda o contêiner. Escutando neste VmId aceita 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 suportado.

Comandos de soquete suportados

Soquete() Bind() Connect() Send() Listen() Accept()

Opções de soquete HvSocket

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

API WinSock completa

Hyper-V referência do Integration Services