Создание собственных служб интеграции
Начиная с юбилейного обновления Windows 10, любой пользователь может сделать приложения, взаимодействующие между узлом Hyper-V и его виртуальными машинами с помощью сокетов Hyper-V — сокета Windows с новым семейством адресов и специализированной конечной точкой для целевых виртуальных машин. Все обмен данными по сокетам Hyper-V выполняются без использования сети, а все данные остаются в одной физической памяти. Приложения, использующие сокеты Hyper-V, похожи на службы интеграции Hyper-V.
В этом документе описывается создание простой программы, созданной на сокетах Hyper-V.
Поддерживаемая ОС узла
- Windows 10 и более поздние версии
- Windows Server 2016 и более поздних версий
Поддерживаемая гостевая ОС
- Windows 10 и более поздние версии
- Windows Server 2016 и более поздних версий
- Гости Linux со службами Linux Integration Services. Сведения о поддерживаемых виртуальных машинах Linux и FreeBSD для Hyper-V в Windows
Примечание.
Ядро поддерживаемой гостевой ОС Linux должно поддерживать следующее:
CONFIG_VSOCKET=y
CONFIG_HYPERV_VSOCKETS=y
Возможности и ограничения
- Поддерживает действия режима ядра или режима пользователя
- Только поток данных
- Нет блочного памяти (не лучше всего для резервного копирования или видео)
Начало работы
Требования:
- Компилятор C/C++. Если у вас его нет, ознакомьтесь с visual Studio Community
- Пакет SDK для Windows — предварительно установлен в Visual Studio 2015 с обновлением 3 и более поздними версиями.
- Компьютер под управлением одной из операционных систем узла, указанных по крайней мере с одним виртуальным компьютером. — это для тестирования приложения.
Примечание. API для сокетов Hyper-V стал общедоступным в юбилейном обновлении Windows 10. Приложения, использующие HVSocket, будут работать на любом хосте и гостевом узле с Widnows 10, но могут создаваться только с помощью пакета SDK для Windows сборки более поздней, чем 14290.
Регистрация нового приложения
Чтобы использовать сокеты Hyper-V, приложение должно быть зарегистрировано в реестре узла Hyper-V.
Зарегистрируя службу в реестре, вы получите:
- Управление WMI для включения, отключения и перечисления доступных служб
- Разрешение на обмен данными с виртуальными машинами напрямую
В следующем powerShell будет зарегистрировано новое приложение с именем HV Socket Demo. Это должно быть запущено от имени администратора. Приведенные ниже инструкции вручную.
$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
Расположение и сведения реестра
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization\GuestCommunicationServices\
В этом расположении реестра вы увидите несколько идентификаторов GUID. Это наши встроенные услуги.
Сведения в реестре для каждой службы:
Service GUID
ElementName (REG_SZ)
-- это понятное имя службы.
Чтобы зарегистрировать собственную службу, создайте новый раздел реестра с помощью собственного GUID и понятного имени.
Понятное имя будет связано с новым приложением. Он будет отображаться в счетчиках производительности и других местах, где GUID не подходит.
Запись реестра выглядит следующим образом:
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
Примечание.
Идентификатор GUID службы для гостевой ОС Linux использует протокол VSOCK, который отправляет запросы через svm_cid
и svm_port
, а не через идентификатор GUID. Для компенсации этого несоответствия в Windows хорошо известный идентификатор GUID используется в качестве шаблона службы на узле, который преобразуется в порт в гостевой ОС. Для настройки идентификатора GUID службы измените первое значение "00000000" на необходимый номер порта. Например, "00000ac9" — порт 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
*/
Совет. Чтобы создать GUID в PowerShell и скопировать его в буфер обмена, используйте следующую команду:
(New-Guid).Guid | clip.exe
Создание сокета Hyper-V
В большинстве случаев для определения сокета требуется семейство адресов, тип подключения и протокол.
Вот простое определение сокета
// Windows
SOCKET WSAAPI socket(
_In_ int af,
_In_ int type,
_In_ int protocol
);
// Linux guest
int socket(int domain, int type, int protocol);
Для сокета Hyper-V:
- Семейство адресов —
AF_HYPERV
(Windows) илиAF_VSOCK
(гостевая ОС Linux) - тип —
SOCK_STREAM
. - Протокол —
HV_PROTOCOL_RAW
(Windows) или0
(гостевая ОС Linux)
Ниже приведен пример объявления или создания экземпляра:
// Windows
SOCKET sock = socket(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW);
// Linux guest
int sock = socket(AF_VSOCK, SOCK_STREAM, 0);
Привязка к сокету Hyper-V
Привязка связывает сокет с сведениями о подключении.
Определение функции копируется ниже для конвинции, ознакомьтесь с дополнительными сведениями о привязке здесь.
// 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);
В отличие от адреса сокета (sockaddr) для стандартного семейства адресов протокола Интернета (AF_INET
), который состоит из IP-адреса хост-компьютера и номера порта на этом узле, адрес сокета для использования идентификатора виртуальной машины и идентификатора приложения, определенного выше, AF_HYPERV
для установления подключения. При привязке через гостевую ОС Linux AF_VSOCK
использует svm_cid
и svm_port
.
Так как сокеты Hyper-V не зависят от сетевого стека, TCP/IP, DNS и т. д. конечная точка сокета, необходимая не ip-адрес, а не имя узла, формат, который по-прежнему однозначно описывает подключение.
Ниже приведено определение адреса сокета 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)];
};
Вместо IP-адреса или имени узла AF_HYPERV конечные точки используют два идентификатора GUID:
Идентификатор виртуальной машины — это уникальный идентификатор, назначенный для каждой виртуальной машины. Идентификатор виртуальной машины можно найти с помощью следующего фрагмента кода PowerShell.
(Get-VM -Name $VMName).Id
Идентификатор службы — GUID, описанный выше, с помощью которого приложение зарегистрировано в реестре узлов Hyper-V.
Существует также набор подстановочных знаков VMID, доступных, если подключение не относится к определенной виртуальной машине.
Подстановочные знаки VMID
Имя. | GUID | Description |
---|---|---|
HV_GUID_ZERO | 00000000-0000-0000-0000-000000000000 | Прослушиватели должны привязаться к этому vmId, чтобы принять подключение со всех разделов. |
HV_GUID_WILDCARD | 00000000-0000-0000-0000-000000000000 | Прослушиватели должны привязаться к этому vmId, чтобы принять подключение со всех разделов. |
HV_GUID_BROADCAST | FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFFFFFF | |
HV_GUID_CHILDREN | 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd | Подстановочный адрес для детей. Прослушиватели должны привязаться к этому vmId, чтобы принять подключение от дочерних элементов. |
HV_GUID_LOOPBACK | e0e16197-dd56-4a10-9195-5ee7a155a838 | Адрес обратного цикла. Использование этого vmId подключается к той же секции, что и соединитель. |
HV_GUID_PARENT | a42e7cda-d03f-480c-9cc2-a4de20abb878 | Родительский адрес. Использование этого VmId подключается к родительской секции соединителя.* |
* HV_GUID_PARENT
Родитель виртуальной машины является его узлом. Родительский элемент контейнера является узлом контейнера.
Подключение из контейнера, работающего на виртуальной машине, будет подключаться к виртуальной машине, в котором размещен контейнер.
Прослушивание этого vmId принимает подключение: (внутри контейнеров): узел контейнера.
(Внутри виртуальной машины: узел контейнера или нет контейнера): узел виртуальной машины.
(Не внутри виртуальной машины: узел контейнера/ нет контейнера): не поддерживается.
Поддерживаемые команды сокета
Socket() Bind() Connect() Send() Listen() Accept()
Параметры сокета HvSocket
Имя. | Тип | Описание |
---|---|---|
HVSOCKET_CONNECTED_SUSPEND | ULONG | Если этот параметр сокета имеет значение, отличное от нуля, не отключается при приостановке виртуальной машины. |