[컴퓨터공학]/[시스템 프로그래밍]

[시스템 프로그래밍] Low-level File IO(1) - Open, Close

딥러닝 도전기 2022. 9. 22. 12:19

[시스템 프로그래밍] Low-level File IO(1) - Open, Close

파일 입출력 방법은 Low-Level File IO (System call)와 High-Level File IO (Buddered IO)로 나뉩니다. 

High-Level File IO는 File pointer를 사용하는 반면, Low-Level File IO는 File descriptor를 사용하여 입출력합니다.

 

이번 포스팅에서는 Low-Level File IO에 대해 알아보겠습니다.

 


1. File open and close

1-1 Open

$ man -s 2 open

man 명령어를 통해 open을 살펴보면 위와 같은 내용을 확인할 수 있습니다.

우선 "open"이라는 System call을 사용하기 위해서는 위에 보이는 세 가지의 헤더파일을 include해야 하는 것을 알 수 있습니다.

 

다음으로 open의 parameter를 살펴보도록 하겠습니다.

 

int open(const char *path, int oflag, /* mode_t mode */)
path : 파일의 이름을 포함한 파일의 경로
flags : 파일을 여는 방법(access mode) 설정
mode(optional) : 파일을 생성할 때만 사용하며 O_CREATE 인자를 사용
( /*   */ 로 표기되어 있는 것은 optional하게 사용하는 것 입니다.

return값은 integer인데 file descriptor를 return하게 됩니다.

 

  • File descriptor(fd, 파일 기술자)?

열려있는 파일을 구분하는 정수값으로 특수 파일 등 대부분의 파일을 지칭할 수 있다. 파일을 열 때 순차적으로 할당되며 Process당 최대 1024개의 fd를 관리할 수 있다.

 

[출처 : 유닉스 시스템 프로그래밍, 한빛 미디어]

Default로 정해져있는 fds는 0, 1, 2 세가지 입니다.

0 : stdin, 표준 입력
1 : stdout, 표준 출력
2 : stderr, 표준 오류

 

  • Flags

O_RDONLY : (ReaD ONLY) 파일을 읽기 전용으로 연다.

O_WRONLY : (WRite ONLY) 파일을 쓰기 전용으로 연다.

O_RDWR : (ReaD WRite) 파일을 읽기와 쓰기가 가능하게 연다.

O_CREAT : 파일이 없으면 파일을 생성한다.

O_EXCL :  O_CREAT 옵션과 같이 사용할 경우 기존에 없는 파일이면 파일을 생성하고, 이미 있다면 에러메시지를 출력한다.

O_APPEND : 파일의 맨 뒤에 내용을 추가한다.

O_TRUNC : 파일을 생성할 때 이미 있는 파일이고 쓰기 옵션으로 열었으면 내용을 모두 지우고 파일의 길이를 0으로 변경한다.

O_SYNC/O_DSYNC : 저장장치에 쓰기가 끝나야 쓰기 동작을 완료

 

위의 Flags는 OR bit operation "|" 를 사용하여 조합이 가능합니다.

 

// ex)
O_WRONLY | O_TRUNC // 파일을 쓰기 모드로 열고, 처음부터 쓰겠다 (내용이 있으면 삭제)
O_RDWR | O_APPEND // 파일을 읽기, 쓰기 모드로 열고 이어서 작성하겠다. (내용 삭제 x)

 

1-2 Close

$ man -s 2 close

 

fildes : file descriptor

return : if success, return 0 
              if error, return -1 

close는 file descriptor를 파라미터로 받고 그에 해당하는 file을 닫습니다.

 


#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;

        mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
        fd = open("hello.txt", O_CREAT | O_EXCL, mode);
        if (fd == -1) {
                perror("EXCL");
                exit(1);
        }
        close(fd);
        return 0;
}

위의 예시는 "hello.txt"라는 파일을 생성하는 예시입니다. 

flag 값으로 O_CREAT | O_EXCL 을 주었기 때문에, 파일이 존재한다면 에러 메시지를 출력합니다.

 

위의 코드를 컴파일한 후 2회 연속으로 실행해보겠습니다.

 

첫번째 실행에서는 hello.txt라는 파일이 생성되었습니다.

두번째 실행에서는 이미 hello.txt라는 파일이 있기 때문에 O_CREAT | O_EXCL 옵션에 의해 에러메시지를 출력합니다.

 


#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int openFile(void){
        int fd = open("hello.txt", O_RDWR);
        if (fd == -1){
                perror("File Open");
                exit(1);
        }
        return fd;
}

int main(void){
        int fd = 0;
        fd = openFile();
        printf("fd = %d\n", fd);
        close(fd);

        close(0);
        fd = openFile();
        printf("fd = %d\n", fd);
        close(fd);
        return 0;
}

 

다음 예시는 file descriptor 값을 확인하는 예시입니다.

0, 1, 2번에는 default 값이 할당되어 있기 때문에 처음 print문에서는 그 다음 번호인 3을 출력합니다.

 

close(0)을 통해 default로 할당된 값을 삭제해주고 file descriptor를 확인하면 0이 출력됩니다.

 

다음 포스팅에는 Read/Write에 관하여 포스팅 하겠습니다.

반응형