Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Начиная с юбилейного обновления 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, будут работать на любом узле и гостях Windows 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 службы, просто измените первый "000000000" на нужный номер порта. Например, "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-FFFFFFFFFFFF | |
| 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 принимает подключения от: (внутри контейнеров): контейнерный хост.
(Внутри виртуальной машины: хост контейнера/без контейнера): хост виртуальной машины.
(Не внутри виртуальной машины: размещение контейнеров / отсутствие контейнера): не поддерживается.
Поддерживаемые команды сокета
Сокет() Привязка() Соединение() Отправка() Прослушивание() Принятие()
Параметры сокета HvSocket
| Имя | Тип | Description |
|---|---|---|
| HVSOCKET_CONNECTED_SUSPEND | ULONG | Если этот параметр сокета установлен в значение, отличное от нуля, сокеты не отключаются при приостановке виртуальной машины. |