본문 바로가기

프로그래밍/미분류

[번역] 디바이스네임과 심볼릭 링크 이해하기

728x90
  • device : 장치, 디바이스
  • device name : 장치이름, 디바이스이름, 디바이스네임, 디바이스명
  • namespace : 명칭공간, 네임스페이스, 이름공간
  • Object Manager : 개체 관리자, 객체 관리자, 오브젝트 매니저, 오브젝트 관리자

디바이스네임과 심볼릭 링크 이해하기 / Understanding Device Names and Symbolic Links

요약 / SUMMARY

하드디스크, 직렬포트, 병렬포트 같은 디바이스(장치)는 기본적으로 내부 윈도우즈 NT 디바이스네임을 갖고, 옵션으로 MS-DOS 디바이스네임도 가질 수 있다. 이 두가지 이름은 윈도우즈 NT 개체 관리자 (Windows NT Object Manager) 이름공간(namespace)에 있게 된다. 윈도우즈 NT와 커널모드 드라이버는 NT 디바이스네임을 사용하지만, Win32 프로그램은 MS-DOS 디바이스네임을 사용해야 한다. MS-DOS 디바이스네임은 하위에 있는 NT 디바이스네임을 가리키는 심볼릭 링크이다. 본 문서는 디바이스네임과 심볼릭 링크, 그리고 Win32 프로그램이 심볼릭 링크를 어떻게 만들거나 없앨 수 있을지를 설명한다.

Devices like hard disks, serial ports, and parallel ports have an internal Windows NT device name and may optionally have an MS-DOS device name. These names are located in the Windows NT Object Manager's namespace. While Windows NT itself and kernel-mode drivers use NT device names, Win32 programs must use the MS-DOS device names. The MS-DOS device name is a symbolic link to the underlying NT device name. This article describes device names, symbolic links, and how Win32 programs can create and remove symbolic links.

추가 정보 / MORE INFORMATION

내부 NT 디바이스네임 / Internal NT Device Names

커널모드 장치 드라이버가 로드되면, 드라이버는 초기화 루틴에서 윈도우즈 NT 개체 관리자(Object Manager)에 디바이스네임을 등록한다. 이 이름을 윈도우즈 NT 디바이스네임이라고 부른다. 윈도우즈 NT의 커널모드 컴포넌트와 커널모드 드라이버는 이 윈도우즈 NT 디바이스네임을 이용하여 장치를 지정하게 된다. 이 이름은 \Device\CDRom0 이나 \Device\Serial0 가 같은 형식으로 되어 있으며, 개체 관리자의 이름공간(네임스페이스) \device 디렉토리에 존재한다.

When a kernel-mode device driver is loaded, its initialization routine registers a device name with Windows NT's Object Manager. This name is referred to as the Windows NT device name. The kernel-mode components of Windows NT and kernel-mode drivers reference devices by their Windows NT device names. These names have a format, such as \Device\CDRom0 and \Device\Serial0 and also exist in the \device directory of the Object Manager's namespace.

Win32 프로그램은 내부 윈도우즈 NT 디바이스네임으로 장치에 접근할 수 없다. 왜냐하면 Win32 서브시스템과 Win32 API는 친숙한 드라이브 알파벳이나 MS-DOS 장치명을 필요로 하기 때문이다. ( A:, C:, COM1:, LPT1: ) 비록, Wind32 프로그램이 윈도우즈 NT 디바이스네임을 사용하지는 않지만, 장치에 접근하기 위한 MS-DOS 디바이스네임을 정의하거나 삭제할 수 있다. 나아가 MS-DOS 디바이스네임과 연결되어 있는 내부 윈도우즈 NT 디바이스네임을 알아낼 수도 있다. 본 아티클 "Symbolic Links" 섹션의 예제 코드가 이를 어떻게 하는지 보여준다.

Win32 programs cannot use internal Windows NT device names to access devices because the Win32 subsystem and Win32 API require the more familiar drive letters and MS-DOS device names, such as A:, C:, COM1:, and LPT1:. Although Win32 programs may not use Windows NT device names, they can however, define and remove MS-DOS device names to access devices. They can also retrieve the internal Windows NT device name associated with an MS-DOS device name. The example code in the "Symbolic Links" section of this article describes how to do this.

개체 관리자가 장치를 비롯한 시스템 개체의 이름을 어떻게 가져오는지를 잘 이해하려면, 플랱폼 SDK의 WinObj.exe 툴로 개체 관리자의 이름공간을 들여다 봐도 좋다.

To gain a better understanding of how the Object Manager tracks names to devices and other system objects, you can view the Object Manager's namespace with the WinObj.exe tool in the Platform SDK.

MS-DOS 장치 이름 / MS-DOS Device Names

Win32 프로그램은 드라이브, 직렬포트, 병렬포트 등의 디바이스를 MS-DOS 디바이스네임을 통해 사용한다. 디스크 드라이버의 경우, A:, C: 같은 드라이브 알파벳이고, 직렬 및 병렬포트에서는 COM1:, COM2:, LPT1: 같은 이름을 사용한다. 윈도우즈 NT 디바이스네임에서 처럼, 이 명칭은 개체 관리자 네임스페이스에 있게 된다. 하지만, 이들은 \?? 디렉토리 아래에 있고, 사용자모드 Win32 프로그램에게도 보인다.

Win32 programs use devices like drives, serial ports, and parallel ports through their MS-DOS device names. For disk drives, these are drive letters like A: and C:. For serial and parallel ports these are names like COM1:, COM2:, and LPT1:. Like Windows NT device names, these names reside in the Object Manager's namespace, but in the ?? directory, which is visible to user-mode Win32 programs.

MS-DOS 디바이스네임이 윈도우즈 NT 디바이스네임과 다른 점은 MS-DOS 디바이스네임은 윈도우즈 NT 커널이나 커널모드 드라이버에 의해 사용되지 않는다는 것이다. MS-DOS 디바이스네임의 목적은 Win32 프로그램이 익숙한 드라이버명이나 장치명으로 윈도우즈 NT 디바이스네임을 가르키기 위함이다. 예를 들면, COM1:으로 윈도우즈 NT 장치를 접근한다. 따라서 MS-DOS 디바이스네임을 윈도우즈 NT 디바이스네임으로의 "심볼 링크"로 부른다. 다시 말하면, MS-DOS 디바이스네임은 개체관리자 \?? 디렉토리에 존재하고, 개체관리자 \device 디렉토리에 있는 윈도우즈 NT 디바이스네임을 가리킨다.

What makes MS-DOS device names different from Windows NT device names is that they are not used by the Windows NT kernel or kernel-mode drivers. Their purpose is to refer to Windows NT device names so that Win32 programs can use the familiar drive letters and device names; for example, COM1:, to access the Windows NT devices. Therefore, MS-DOS device names are called "symbolic links" to Windows NT device names. That is, an MS-DOS device name exists in the Object Manager's ?? directory and points to a Windows NT device name in the Object Manager's \device directory.

MS-DOS 디바이스네임 한 개는 한 개 이상의 내부 윈도우즈 NT 장치를 가리킬 수 없다. 그렇지만, MS-DOS 디바이스네임 여러 개가 한 개의 장치를 가리키는 것은 괜찮다. 예를 들어, C:는 하나의 파티션만 가리킬 수 있지만, D:, E:, Z: 같이 다른 드라이버 알파벳으로 동일한 파티션을 가리킬 수 있다.

Each MS-DOS device name can point to at most one internal Windows NT device. However, multiple MS-DOS device names can point to a single device. For example, while C: can only point to a single partition, it is possible to have two or more drive letters, like D:, E:, and Z:, point to the same partition.

심볼 링크 / Symbolic Links

시스템이 생성한 심볼 링크는 레지스트리에 보관되기 때문에 재시작해도 계속 살아있다. 프로그램은 DefineDosDevice() API를 이용해서 심볼 링크를 만들 수도 있다. 이 링크는 링크에 대한 정보를 가진 레지스트리가 만들어지지 않는 한은 시스템이 꺼지기 전까지만 유효하다. 한 개의 윈도우즈 NT 디바이스 네임에 대해 여러 개의 심볼 링크가 있어도 된다. 그러나, 시스템이 내부 윈도우즈 NT 디바이스에 처음 지정한 MS-DOS 디바이스 네임만이 재부팅을 해도 유지된다. 따라서, 하나의 CD-ROM 드라이버를 가리키는 여러 개의 드라이브 알파벹 심볼링크를 만들 수 있지만, 나머지 드라이브 알파벹은 시스템이 꺼지기 전까지만 살아있다.

Symbolic links created by the system persist across computer restarts because they are stored in the registry. Programs may also create symbolic links with the DefineDosDevice() API. These links are valid only until the computer is restarted or turned off unless the registry keys containing information about the links are updated.

There can be multiple symbolic links to a Windows NT device name. However, only the MS-DOS device name that the system initially assigned to the internal Windows NT device remains across reboots. Therefore, it is possible to create additional symbolic links that assign multiple drive letters to a single CD-ROM drive, but the additional drive letters only remain until the machine is turned off or restarted.

Win32 프로그램은 QueryDosDevice() 에 MS-DOS 디바이스 네임을 인자로 호출하여 특정 MS-DOS 디바이스네임에 연결된 윈도우즈 NT 디바이스 네임을 가져올 수 있다. 아래가 예제 코드다.

Win32 programs can retrieve the Windows NT device name that is associated with a specific MS-DOS device name by calling QueryDosDevice() with the MS-DOS device name. Following is example code that shows how to do this:

char szNtDeviceName[MAX_PATH];

if (QueryDosDevice ("C:", szNtDeviceName, MAX_PATH))
{
   printf ("C: is linked to %s\n", szNtDeviceName);
}

Win32 프로그램은 DefineDosDevice() 를 호출하여 심볼 링크를 생성, 삭제할 수 있다. 심볼 링크를 새로 만들려면, DDD_RAW_TARGET_PATH 플랙을 세워서 DefineDosDevice 를 호출한다. 심볼 링크를 없애려면, DDD_REMOVE_DEFINITIONDDD_RAW_TARGET_PATH 플랙을 세워서 호출한다. 아래 샘플코드에서 이 두가지 조작을 예시한다.

Win32 programs can create and delete symbolic links by calling DefineDosDevice(). To create a symbolic link, call DefineDosDevice with the DDD_RAW_TARGET_PATH flag. To remove a symbolic link, call it with the DDD_REMOVE_DEFINITION and DDD_RAW_TARGET_PATH flags. The following sample program demonstrates both of these operations:

/*
   DDD

      This sample shows how to associate an MS-DOS device name with a 
      Windows NT device name. The association is a symbolic link between
      device names stored in the Object Manager's namespace. Applications
      use the MS-DOS device name, but Windows NT and kernel-mode drivers
      use the Windows NT device name.  

   Usage:
      ddd <MS-DOS Device Name> <NT Device Name>
      ddd -r <MS-DOS Device Name>

   NOTE: If the MS-DOS device name is a driver letter, the trailing 
   backlash is not accepted by DefineDosDevice or QueryDosDevice.

   NOTE: The MS-DOS device name is defined only until the computer is 
   restarted.

   To make the drive letter associations permanent on Window NT 4.0, you
   have to update HKEY_LOCAL_MACHINE\SYSTEM\DISK\Information. However, 
   the contents of the value are undocumented. 

   On Windows 2000, you have to use the Volume Mount Point APIs.
*/ 

#define WIN32_LEAN_AND_MEAN /* Reduce number of system headers parsed */ 
                            /* during build. */ 

#include <windows.h>
#include <stdio.h>

void main (int argc, char **argv)
{
   char * pszDosDeviceName,
        * pszNtDeviceName;

   bool  fRemoveDeviceName = false;
   bool  fResult;

   /*
      Command-line parsing.
        1) Make sure correct number of arguments are supplied.
        2) See if you should add or remove the MS-DOS Device Name.
   */ 
   if (argc != 3)
   {
      printf("\nusage: %s <DOS device name> <NT device name>    to add\n",
             argv[0]);
      printf("usage: %s [-r] <DOS device name>                to remove\n",
             argv[0]);
      printf("\n\texample: %s d: \\device\\cdrom0\n", argv[0]);
      return;
   }

   fRemoveDeviceName = !lstrcmpi (argv[1], "-r");


   /* Now, add/remove the DOS device name. */ 
   if (fRemoveDeviceName)
   {
      /*
         Remove the MS-DOS device name. First, get the name of the Windows
         NT device from the symbolic link, then delete the symbolic link.

      */ 
      pszDosDeviceName = argv[2];

      pszNtDeviceName = (char *)LocalAlloc (LPTR, MAX_PATH);

      fResult = QueryDosDevice (pszDosDeviceName, pszNtDeviceName,
                                MAX_PATH);
      if (fResult)
      {
         fResult = DefineDosDevice (DDD_RAW_TARGET_PATH|
                                    DDD_REMOVE_DEFINITION|
                                    DDD_EXACT_MATCH_ON_REMOVE,
                                    pszDosDeviceName, pszNtDeviceName);
      }
      if (!fResult)
         printf("error %lu: could not remove %s\n",
                GetLastError(), pszDosDeviceName);

      LocalFree (pszNtDeviceName);
   }
   else
   {
      /* Add the DOS device name */ 

      pszDosDeviceName = argv[1];
      pszNtDeviceName  = argv[2];

      fResult = DefineDosDevice (DDD_RAW_TARGET_PATH, pszDosDeviceName,
                                 pszNtDeviceName);
      if (!fResult)
         printf("error %lu: could not link %s to %s\n",
                GetLastError(), pszDosDeviceName, pszNtDeviceName);
   }

}

https://support.microsoft.com/en-us/help/235128/info-understanding-device-names-and-symbolic-links