다음을 통해 공유


사용자 고유의 통합 서비스 만들기

Windows 10 1주년 업데이트부터는 누구나 Hyper-V 소켓을 사용하여 Hyper-V 호스트와 가상 머신 간에 통신하는 애플리케이션(새 주소 패밀리가 있는 Windows 소켓 및 가상 머신을 대상으로 하는 특수 엔드포인트)을 만들 수 있습니다. Hyper-V 소켓을 통한 모든 통신은 네트워킹을 사용하지 않고 실행되며 모든 데이터는 동일한 실제 메모리에 유지됩니다. Hyper-V 소켓을 사용하는 애플리케이션은 Hyper-V의 통합 서비스와 유사합니다.

이 문서에서는 Hyper-V 소켓을 기반으로 하는 간단한 프로그램을 만드는 방법에 대해 설명합니다.

지원되는 호스트 OS

  • Windows 10 이상
  • Windows Server 2016 이상

지원되는 게스트 OS

  • Windows 10 이상
  • Windows Server 2016 이상
  • Linux Integration Services를 사용하는 Linux 게스트. Windows에서 Hyper-V에 대해 지원되는 Linux 및 FreeBSD 가상 머신을 참조하세요 .

참고 항목

지원되는 Linux 게스트는 다음에 대해 커널을 지원해야 합니다.

CONFIG_VSOCKET=y
CONFIG_HYPERV_VSOCKETS=y

기능 및 제한 사항

  • 커널 모드 또는 사용자 모드 작업을 지원합니다.
  • 데이터 스트림만
  • 블록 메모리 없음(백업/비디오에 최적이 아님)

시작

요구 사항:

  • C/C++ 컴파일러. 없는 경우 Visual Studio 커뮤니티를 체크 아웃 합니다.
  • Windows SDK - 업데이트 3 이상과 함께 Visual Studio 2015에 미리 설치됩니다.
  • 하나 이상의 가상 머신으로 지정된 호스트 운영 체제 중 하나를 실행하는 컴퓨터입니다. -- 애플리케이션을 테스트하기 위한 것입니다.

참고: Hyper-V 소켓용 API는 Windows 10 1주년 업데이트에서 공개되었습니다. HVSocket을 사용하는 애플리케이션은 Windows 10 호스트와 게스트에서 실행되지만 빌드 14290 이후의 Windows SDK로만 개발할 수 있습니다.

새 애플리케이션 등록

Hyper-V 소켓을 사용하려면 애플리케이션을 Hyper-V 호스트의 레지스트리에 등록해야 합니다.

레지스트리에 서비스를 등록하면 다음을 얻을 수 있습니다.

  • 사용 가능한 서비스를 사용, 사용 안 함 및 나열하기 위한 WMI 관리
  • 가상 머신과 직접 통신할 수 있는 권한

다음 PowerShell은 "HV 소켓 데모"라는 새 애플리케이션을 등록합니다. 관리자 권한으로 실행해야 합니다. 아래의 수동 지침입니다.

$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

참고 항목

Linux 게스트용 서비스 GUID는 GUID가 아니라 svm_cidsvm_port를 통해 주소 지정이 되는 VSOCK 프로토콜을 사용합니다. 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
  */

팁: PowerShell에서 GUID를 생성하고 클립보드에 복사하려면 다음을 실행합니다.

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

호스트 컴퓨터의 IP 주소와 해당 호스트의 포트 번호로 구성된 표준 인터넷 프로토콜 주소 패밀리()의 소켓 주소(AF_INETsockaddr)와는 달리, 소켓 주소 AF_HYPERV 는 가상 머신의 ID와 위에서 정의한 애플리케이션 ID를 사용하여 연결을 설정합니다. Linux 게스트 AF_VSOCK의 바인딩에서 svm_cidsvm_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에 크게 의존합니다.

  • VM ID – VM당 할당된 고유 ID입니다. 다음 PowerShell 코드 조각을 사용하여 VM의 ID를 찾을 수 있습니다.

    (Get-VM -Name $VMName).Id
    
  • 서비스 ID – 위에서 설명한 GUID로, Hyper-V 호스트 레지스트리에 애플리케이션이 등록됩니다.

특정 가상 머신에 연결하지 않을 때 사용할 수 있는 VMID 와일드카드 집합도 있습니다.

VMID 와일드카드

속성 GUID 설명
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-FFFFFFFFFF
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 가상 머신의 부모는 해당 호스트입니다. 컨테이너의 부모는 컨테이너의 호스트입니다. 가상 머신에서 실행되는 컨테이너에서 연결하면 컨테이너를 호스팅하는 VM에 연결됩니다. 이 VmId에서 수신 대기하면 다음(컨테이너 내부): 컨테이너 호스트에서 연결을 허용합니다. (VM 내부: 컨테이너 호스트/컨테이너 없음): VM 호스트. (VM 내부에 없음: 컨테이너 호스트/컨테이너 없음): 지원되지 않습니다.

지원되는 소켓 명령

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

HvSocket 소켓 옵션

속성 형식 설명
HVSOCKET_CONNECTED_SUSPEND ULONG 이 소켓 옵션이 0이 아닌 값 소켓으로 설정된 경우 가상 머신이 일시 중지될 때 연결이 끊어지지 않습니다.

WinSock API 완료

Hyper-V 통합 서비스 참조