파일 만들기 및 열기
CreateFile 함수는 새 파일을 만들거나 기존 파일을 열 수 있습니다. 파일 이름, 만들기 지침 및 기타 특성을 지정해야 합니다. 애플리케이션이 새 파일을 만들면 운영 체제는 이 파일을 지정된 디렉터리에 추가합니다.
운영 체제는 CreateFile 을 사용하여 열거나 만드는 각 파일에 핸들이라는 고유 식별자를 할당합니다. 애플리케이션은 이 핸들을 파일을 읽고, 쓰고, 설명하는 함수와 함께 사용할 수 있습니다. 이것은 핸들에 대한 모든 참조가 닫힐 때까지 유효합니다. 애플리케이션이 시작되면 애플리케이션을 시작한 프로세스에서 열려있는 모든 핸들을 상속합니다(핸들을 상속 가능하게 만든 경우).
애플리케이션은 핸들을 사용하여 파일에 액세스하려고 시도하기 전에 CreateFile에 의해 반환된 핸들 값을 확인해야 합니다. 오류가 발생하면 핸들 값은 INVALID_HANDLE_VALUE가 되고 애플리케이션은 GetLastError 함수를 확장된 오류 정보에 사용할 수 있습니다.
애플리케이션이 CreateFile을 사용하는 경우 dwDesiredAccess 매개 변수를 사용하여 파일에서 읽을 것인지, 파일에 쓸 것인지, 읽기와 쓰기를 모두 할 것인지, 둘 다 하지 않을 것인지를 지정해야 합니다. 이를 액세스 모드 요청이라고 합니다. 또한 애플리케이션은 dwCreationDisposition 매개 변수를 사용하여 파일이 이미 있는 경우 수행할 작업(만들기 처리라고도 함)을 지정해야 합니다. 예를 들어 애플리케이션은 dwCreationDisposition이 CREATE_ALWAYS로 설정된 CreateFile을 호출하여 같은 이름의 파일이 이미 있는 경우에도 항상 새 파일을 만들 수 있습니다(따라서 기존 파일 덮어씁니다). 이 작업의 성공 여부는 이전 파일의 특성 및 보안 설정과 같은 요소에 따라 달라집니다(자세한 내용은 다음 섹션 참조).
또한 애플리케이션은 CreateFile을 사용하여 읽기, 쓰기 또는 둘 다 가능 또는 불가능하도록 파일을 공유할지 여부를 지정합니다. 이를 공유 모드라고 합니다. 공유되지 않은 열린 파일(dwShareMode이 0으로 설정됨)은 핸들이 닫힐 때까지 해당 파일을 연 애플리케이션이나 다른 애플리케이션에서 다시 열 수 없습니다. 이를 단독 액세스라고도 합니다.
프로세스가 CreateFile을 사용하여 공유 모드(dwShareMode가 0이 아닌 유효한 값으로 설정됨)에서 이미 열려있는 파일을 열려고 시도하면 시스템은 요청된 액세스 및 공유 모드를 파일이 열렸을 때 지정된 것과 비교합니다. 이전 호출에서 지정한 모드와 충돌하는 액세스 또는 공유 모드를 지정하면 CreateFile이 실패합니다.
다음 표는 다양한 액세스 모드 및 공유 모드(각각 dwDesiredAccess, dwShareMode)를 사용하여 CreateFile에 대한 두 호출의 유효한 조합을 보여줍니다. CreateFile 호출이 수행되는 순서는 중요하지 않습니다. 그러나 각 파일 핸들에 대한 후속 파일 I/O 작업은 해당 특정 파일 핸들과 연결된 현재 액세스 및 공유 모드에 의해 여전히 제한됩니다.
CreateFile에 대한 첫 번째 호출 | CreateFile에 대한 유효한 두 번째 호출 |
---|---|
GENERIC_READ, FILE_SHARE_READ |
|
GENERIC_READ, FILE_SHARE_WRITE |
|
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE
|
GENERIC_WRITE, FILE_SHARE_READ |
|
GENERIC_WRITE, FILE_SHARE_WRITE |
|
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE
|
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ |
|
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_WRITE |
|
GENERIC_READ, GENERIC_WRITE, FILE_SHARE_READ, FILE_SHARE_WRITE |
|
표준 파일 특성 외에도 SECURITY_ATTRIBUTES 구조체에 대한 포인터를 CreateFile의 네 번째 매개 변수로 포함하여 보안 특성을 지정할 수도 있습니다. 단, 이것이 영향을 미치려면 기본 파일 시스템이 보안을 지원해야 합니다. (예를 들어, NTFS 파일 시스템은 지원하지만 다양한 FAT 파일 시스템은 지원하지 않습니다.) 보안 특성에 대한 자세한 내용은 액세스 제어를 참조하세요.
새 파일을 만드는 애플리케이션은 템플릿 파일에 선택적 핸들을 제공할 수 있으며, 여기에서 CreateFile은 파일 특성 및 확장 특성을 사용하여 새 파일을 만들 수 있습니다.
CreateFile 시나리오
CreateFile 함수를 사용하여 파일에 대한 액세스를 시작하는 몇 가지 기본적인 시나리오가 있으며, 다음과 같이 요약됩니다.
- 같은 이름의 파일이 이미 존재하지 않는 경우 새 파일 만들기
- 같은 이름의 파일이 이미 있더라도 새 파일을 만들고, 해당 데이터를 지우고 빈 상태로 시작하기
- 기존 파일이 존재하고 온전한 경우에만 기존 파일 열기
- 기존 파일이 존재하는 경우에만 열고 파일을 잘라서 비우기
- 항상 파일 열기(파일이 있으면 그대로, 없으면 새로 만들어서)
이러한 시나리오는 dwCreationDisposition 매개 변수를 적절히 사용하여 제어됩니다. 다음은 이러한 시나리오가 이 매개 변수의 값에 매핑되는 방식과 이 시나리오를 사용할 때 발생하는 상황에 대한 분석입니다.
같은 이름의 파일이 아직 없을 때 새 파일을 만들거나 열면(dwCreationDisposition이 CREATE_NEW, CREATE_ALWAYS 또는 OPEN_ALWAYS로 설정됨) CreateFile 함수는 다음 작업을 수행합니다.
- dwFlagsAndAttributes에 의해 지정된 파일 특성 및 플래그를 FILE_ATTRIBUTE_ARCHIVE와 결합합니다.
- 파일 길이를 0으로 설정합니다.
- hTemplateFile 매개 변수가 지정된 경우 템플릿 파일이 제공하는 확장 특성을 새 파일에 복사합니다(그러면 이전에 지정한 모든 FILE_ATTRIBUTE_* 플래그가 재정됨).
- bInheritHandle 멤버에 의해 지정된 상속 플래그 및 lpSecurityAttributes 매개 변수(SECURITY_ATTRIBUTES 구조체)의 lpSecurityDescriptor 멤버에 의해 지정된 보안 설명자를 설정합니다(제공된 경우).
같은 이름의 파일이 이미 있더라도 새 파일을 만드는 경우(dwCreationDisposition이 CREATE_ALWAYS로 설정됨) CreateFile 함수는 다음 작업을 수행합니다.
- 현재 파일 특성 및 쓰기 액세스에 대한 보안 설정을 확인합니다. 거부된 경우 실패합니다.
- dwFlagsAndAttributes에 의해 지정된 파일 특성 및 플래그를 FILE_ATTRIBUTE_ARCHIVE 및 기존 파일 특성과 결합합니다.
- 파일 길이를 0으로 설정합니다(즉, 파일에 있던 모든 데이터를 더 이상 사용할 수 없고 파일이 비어있음).
- hTemplateFile 매개 변수가 지정된 경우 템플릿 파일이 제공하는 확장 특성을 새 파일에 복사합니다(그러면 이전에 지정한 모든 FILE_ATTRIBUTE_* 플래그가 재정됨).
- lpSecurityAttributes 매개 변수(SECURITY_ATTRIBUTES 구조체)의 bInheritHandle 멤버에 의해 지정된 상속 플래그를 설정하지만(제공된 경우) SECURITY_ATTRIBUTES 구조체의 lpSecurityDescriptor 멤버는 무시합니다.
- 달리 성공한 경우(즉, CreateFile이 유효한 핸들을 반환하는 경우) GetLastError를 호출하면 ERROR_ALREADY_EXISTS 코드가 생성됩니다. 이 특정 사용 사례의 경우 실제로는 오류가 아닙니다(기존 파일 대신 "새"(빈) 파일을 만들려는 경우).
기존 파일을 열 때(dwCreationDisposition이 OPEN_EXISTING, OPEN_ALWAYS 또는 TRUNCATE_EXISTING으로 설정됨) CreateFile 함수는 다음 작업을 수행합니다.
- 요청된 액세스에 대한 현재 파일 특성 및 보안 설정을 확인합니다. 거부된 경우 실패합니다.
- dwFlagsAndAttributes에 의해 지정된 파일 플래그(FILE_FLAG_*)를 기존 파일 특성과 결합하고 dwFlagsAndAttributes에 의해 지정된 파일 특성(FILE_ATTRIBUTE_*)을 무시합니다.
- dwCreationDisposition이 TRUNCATE_EXISTING으로 설정된 경우에만 파일 길이를 0으로 설정합니다. 그렇지 않으면 현재 파일 길이가 유지되고 파일이 있는 그대로 열립니다.
- hTemplateFile 매개 변수를 무시합니다.
- lpSecurityAttributes 매개 변수(SECURITY_ATTRIBUTES 구조체)의 bInheritHandle 멤버에 의해 지정된 상속 플래그를 설정하지만(제공된 경우) SECURITY_ATTRIBUTES 구조체의 lpSecurityDescriptor 멤버는 무시합니다.
파일 특성 및 디렉터리
파일 특성은 파일 또는 디렉터리와 연결된 메타데이터의 일부이며, 각각 고유한 용도와 설정 및 변경 방법에 대한 규칙이 있습니다. 이러한 특성 중 일부는 파일에만 적용되고 일부는 디렉터리에만 적용됩니다. 예를 들어 FILE_ATTRIBUTE_DIRECTORY 특성은 디렉터리에만 적용됩니다. 파일 시스템에서 디스크의 개체가 디렉터리인지 여부를 확인하는 데 사용되지만 기존 파일 시스템 개체에 대해 변경할 수는 없습니다.
일부 파일 특성은 디렉터리에 대해 설정할 수 있지만 해당 디렉터리에서 만든 파일에 대해서만 의미가 있으며 기본 특성으로 작동합니다. 예를 들어 FILE_ATTRIBUTE_COMPRESSED는 디렉터리 개체에 설정할 수 있지만 디렉터리 개체 자체에는 실제 데이터가 포함되어 있지 않기 때문에 실제로 압축되지는 않습니다. 하지만 이 특성으로 표시된 디렉터리는 해당 디렉터리에 추가된 새 파일을 압축하도록 파일 시스템에 지시합니다. 디렉터리에 설정할 수 있고 해당 디렉터리에 추가되는 새 파일에 대해서도 설정되는 파일 특성을 상속된 특성이라고 합니다.
CreateFile 함수는 파일을 만들 때 특정 파일 특성을 설정하기 위한 매개 변수를 제공합니다. 일반적으로 이러한 특성은 파일을 만들 때 애플리케이션이 가장 일반적으로 사용하지만 가능한 모든 파일 특성 중 일부는 CreateFile에서 사용할 수 없습니다. 일부 파일 특성에는 파일이 이미 존재하면 SetFileAttributes, DeviceIoControl 또는 DecryptFile과 같은 다른 함수를 사용해야 합니다. FILE_ATTRIBUTE_DIRECTORY의 경우 생성 시 CreateDirectory 함수가 필요합니다. CreateFile은 디렉터리를 만들 수 없기 때문입니다. 특수 처리가 필요한 다른 파일 특성은 FILE_ATTRIBUTE_REPARSE_POINT 및 FILE_ATTRIBUTE_SPARSE_FILE입니다(DeviceIoControl 필요). 자세한 내용은 SetFileAttributes를 참조하세요.
앞에서 설명한 것처럼 파일 특성 상속은 파일이 있는 디렉터리 특성에서 읽은 파일 특성으로 파일을 만들 때 발생합니다. 다음 표에는 상속된 특성 및 이 특성과 CreateFile 기능과의 관계가 요약되어 있습니다.
디렉터리 특성 상태 | 새 파일에 대한 CreateFile 상속 재정의 기능 |
---|---|
FILE_ATTRIBUTE_COMPRESSED가 설정됨 |
컨트롤이 없습니다. DeviceIoControl을 사용하여 지웁니다. |
FILE_ATTRIBUTE_COMPRESSED가 설정되지 않음 |
컨트롤이 없습니다. DeviceIoControl을 사용하여 설정합니다. |
FILE_ATTRIBUTE_ENCRYPTED가 설정됨 |
컨트롤이 없습니다. DecryptFile을 사용합니다. |
FILE_ATTRIBUTE_ENCRYPTED가 설정되지 않음 |
CreateFile을 사용하여 설정할 수 있습니다. |
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED가 설정됨 |
컨트롤이 없습니다. SetFileAttributes를 사용하여 지웁니다. |
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED가 설정되지 않음 |
컨트롤이 없습니다. SetFileAttributes를 사용하여 설정합니다. |