저수준 파일 입출력
저수준 파일 입출력은 byte 단위로 입출력을 수행한다. 저수준 파일 입출력을 이용하면 일반 파일뿐만 아니라 특수 파일도 읽고 쓸 수 있다. 저수준 파일 입출력은 System call이다.
File Descriptor
모든 저수준 파일 입출력 함수는 file descriptor를 사용한다.
file descriptor는 현재 열려 있는 파일을 구분할 목적으로 UNIX에서 붙여놓은 번호이며 열린 파일을 참조하는 데 사용하는 지시자 역할을 한다.
file descriptor는 open 함수를 사용해 파일을 열었을 때 부여된다.
0번부터 시작하는데 0, 1, 2번 file descriptor는 기본적으로 용도가 지정되어 있는 상태이다.
- 0번: standard input
- 1번: standard output
- 2번: standard error
보통 0번은 키보드, 1번은 모니터 화면을 의미한다.
0~2번의 file descriptor는 다른 파일에 지정할 수도 있다.
process가 파일을 열 때 file descriptor는 0번부터 시작해 가장 작은 번호가 자동으로 할당된다.
process가 처음 동작할 때 세 파일 기술자는 기본적으로 할당되며 process가 파일을 처음 열면 3번 file descriptor가 할당된다.
0, 1, 2번 file descriptor를 닫아놓았을 경우 이들 번호도 할당될 수 있다.
파일 생성과 열고 닫기
파일을 읽고 쓰려면 당연하게도 우선 파일을 열어야 할 것이다.
"파일을 연다" -> 파일의 내용을 읽거나 파일에 내용을 쓸 수 있는 상태로 변경하는 것
파일에 대한 작업을 완료하면 파일을 닫아야 하는데, 그래야 1. 파일의 내용을 온전히 기록할 것이고 2. 파일이 사용한 buffer 등을 반납할 수 있다.
open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *path, int oflag [, mode_t mode]);
- path: 열고자 하는 파일이 있는 경로
- oflag: 파일 상태 플래그
- mode: 접근 권한
파일의 상태를 조정하는 oflag 값은 <sys/fcntl.h>(/usr/include/sys/fcntl.h) 파일에 #define O_RDWR 2와 같이 정의되어 있다.
mode는 <sys/stat.h> 파일에 정의된 플래그를 사용할 수 있다.
<sys/types.h>에는 시스템에서 사용하는 자료형에 관한 정보들을 담고있다.
주요 oflag
파일의 상태를 조정한다.
종류 | 기능 |
O_RDONLY | 파일을 읽기 전용으로 연다. |
O_WRONLY | 파일을 쓰기 전용으로 연다. |
O_RDWR | 파일을 읽기/쓰기용으로 연다. |
O_CREAT | 파일이 없으면 생성한다. 파일을 생성할 권한이 있어야 한다. 파일이 이미 있다면 의미 없어지는 옵션. |
O_EXCL | O_CREAT 옵션과 함께 사용할 경우 기존에 없는 파일이면 파일을 생성. 이미 있으면 파일을 생성하지 않고 오류 메시지를 출력한다. |
O_APPEND | 파일의 맨 끝에 내용을 추가한다. |
O_TRUNC | 파일을 생성할 때 이미 있는 파일이고, 쓰기 옵션으로 열었으면 내용을 모두 지우고 파일의 길이를 0으로 변경한다. |
O_NONBLOCK/O_NDELAY | non-blocking 입출력 옵션으로 파일을 읽거나 쓰고 난 후의 동작에 영향을 준다. disk의 파일 입출력보다 FIFO 같은 특수 파일의 입출력에 의미가 있다. disk인 경우 읽거나 쓸 data가 없으면 -1을 리턴한다. |
O_SYNC/ODSYNC | 파일에 쓰기 동작을 할 때 보통 buffer에만 쓰고 나중에 disk와 같은 저장 장치로 옮겨 쓴다. 이 옵션이 설정되어 있으면 저장 장치에 쓰기를 마쳐야 쓰기 동작을 완료한다. O_SYNC 플래그는 파일의 수정 시각 속성도 수정할 때까지 기다린다. 이 옵션을 설정하면 프로그램 실행 속도는 느려지게 될테지만, disk에 확실하게 저장됨을 보장한다. |
플래그는 OR 연산자로 연결해 지정할 수 있다.
쓰기 전용으로 열 때, 이미 파일이 있는 경우 | O_WRONLY | O_TRUNC |
쓰기 전용으로 열 때, 파일이 없는 경우 | O_WRONLY | O_CREAT | O_TRUNC |
읽기/쓰기/추가용으로 열 때 | O_RDWR | O_APPEND |
mode는 파일의 접근 권한을 설정한다. O_CREAT 플래그를 지정해 파일을 생성할 때만 사용한다.
플래그 | 모드 | 설명 |
S_IRWXU | 0700 | 소유자 읽기/쓰기/실행 권한 |
S_IRUSR | 0400 | 소유자 읽기 권한 |
S_IWUSR | 0200 | 소유자 쓰기 권한 |
S_IXUSR | 0100 | 소유자 실행 권한 |
S_IRWXG | 0070 | 그룹 읽기/쓰기/실행 권한 |
S_IRGRP | 0040 | 그룹 읽기 권한 |
S_IWGRP | 0020 | 그룹 쓰기 권한 |
S_IXGRP | 0010 | 그룹 실행 권한 |
S_IRWXO | 0007 | 기타 사용자 읽기/쓰기/실행 권한 |
S_IROTH | 0004 | 기타 사용자 읽기 권한 |
S_IWOTH | 0002 | 기타 사용자 쓰기 권한 |
S_IXOTH | 0001 | 기타 사용자 실행 권한 |
표를 이용해 0644 권한을 지정하려면 OR 연산자를 다음과 같이 이용하면 된다.
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
각 자리의 수를 더한 값이 된다.
파일 열기에 성공하면 file descriptor를 리턴하며, 실패할 경우 -1을 리턴하고 외부 변수인 errno에 실패한 이유를 설명하는 오류 코드를 저장한다. 이 오류 코드는 perror 함수로 출력하여 확인할 수 있다.
close
#include <unistd.h>
int close(int fildes);
- fildes: file descriptor를 의미한다.
파일을 닫는 데에 close 함수를 사용한다. 파일 입출력 작업을 완료하면 반드시 close를 통해 파일을 닫아야 하는데, process가 열 수 있는 파일의 개수가 제한되어 있기 때문이다. 제대로 닫지 않고 open만 하다 보면 최대 허용 개수를 초과해 더 이상 파일을 열지 못할 수 있다.
close 함수는 파일을 성공적으로 닫으면 0을 리턴하고 실패하면 -1을 리턴한다. 오류코드는 외부 변수 errno에 저장된다.
Example
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int fd;
mode_t mode;
// fd = open("unix.txt", O_CREAT, 0644);
// fd = open("unix.txt", O_CREAT|O_EXCL, 0644);
// fd = open("unix.txt", O_CREAT|O_TRUNC, 0644);
fd = open("unix.txt", O_CREAT|O_RDWR, 0644);
if (fd == -1) {
perror("Creat");
exit(1);
}
close(fd);
return 0;
}
'Unix' 카테고리의 다른 글
memcpy, strcpy 문자열 복사 차이&사용법 (0) | 2022.10.10 |
---|---|
저수준 파일 입출력 (read, write) (1) | 2022.09.21 |