저수준 파일 입출력과 고수준 파일 입출력을 비교해보자!

funky·2023년 10월 28일
0
post-thumbnail
post-custom-banner

저수준(low-level) 파일 입출력

파일 기술자(file discriptor)

파일 기술자는 현재 열려 있는 파일을 구분할 목적으로 시스템에서 붙여놓은 번호

fd의 특징

  • open()함수로 파일을 열 때 부여됨 -> 열린 파일을 참조하는 데 사용하는 지시자 역할을 한다!
  • 0번 부터 시작하는데, 0번, 1번, 2번 fd는 기본적인 용도가 지정되어 있음
	0: 표준 입력(standard input)
    1: 표준 출력(standard output)
    2: 표준 오류(standard error)
  • 프로세스가 파일을 열 때 순서대로 가장 작은 번호가 자동 할당되므로, 처음 파일을 열면 3번이 할당됨
물론, 0,1,2 fd를 닫아놓으면 0,1,2에도 할당 가능 

open() : 파일 열기

파일을 연다는 것은 파일의 내용을 읽거나 파일에 내용을 쓸 수 있는 상태로 변경하는 것 !

  • 파일 열기에 성공하면 파일 기술자(fd)를 리턴
  • 실패하면 -1을 리턴하고 errno에 실패 이유를 설명하는 오류 코드 저장
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

//pathname : 열려는 파일이 있는 경로
//flags : 파일 상태 플래그
//mode : 접근 권한 - 0644 같이 지정하거나 상숫값(S_IROTH 등)으로도 지정가능

주요 flags

플래그는 OR 연산자를 사용해 연결도 가능!


creat() : 파일 생성

  • 파일을 생성하는 전용 함수
  • 구버전 유닉스에서 사용하던 것으로 open()함수와 달리 플래그를 지정하는 부분이 없다
// 다음 두 함수는 같은 기능을 한다 !
creat(pathname, mode);
open(pathname, O_CREAT | O_O_WRONLY | O_TRUNC, mode);

close() : 파일 닫기

입출력 작업을 모두 완료하면 무조건 파일을 닫자 !

한 프로세스가 열 수 있는 파일 개수에 제한이 있어, 파일을 제대로 닫지 않으면 최대 허용 개수를 초과해 더 이상 파일을 열지 못할 수 있다

#include <unistd.h>

int close(int fd);
  • 파일을 성공적으로 닫으면 0을 리턴
  • 파일 닫기에 실패하면 -1을 리턴하고 오류 코드를 errno에 저장

0번 fd를 닫았을 때 어떤 일이 발생할까?

// 0번 fd를 닫았을 때 어떤 일이 발생할까?

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main() {
	int fd;
    
    close(0);
    
    fd = open("test.txt", O_RDWR);
    if(fd == -1){
   	 	perror("open");
    	exit(1);
    }
    
    printf("test.txt : fd = %d\n", fd); // test.txt : fd = 0
    close(fd);
}

read() : 파일 읽기

데이터가 텍스트든 이미지든 무조건 바이트 단위 로 읽음에 주의!

파일 기술자가 가리키는 파일에서 count에 지정한 크기만큼 바이트를 읽어 buf로 저장한 메모리 영역에 저장한다.

  • 실제 읽은 바이트 수를 리턴하며 오류가 발생하면 -1을 리턴

  • 리턴값이 0이면 파일의 끝에 도달해 더 이상 읽을 내용이 없다는 것

  • read()함수 실행할 때마다 읽은 크기만큼 오프셋이 이동해 다음 읽을 위치를 가리킨다.

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

//fd : 파일 기술자
//buf : 파일에 기록할 데이터를 저장한 메모리 영역 
//count : buf의 크기(기록할 데이터의 크기)

write() : 파일 읽기

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

//fd : 파일 기술자 - 쓰기를 수행할 파일 
//buf : 파일에 기록할 데이터를 저장한 메모리 영역 
//count : buf의 크기(기록할 데이터의 크기)

buf가 가리키는 메모리 영역에서 count로 지정한 크기만큼 읽어 파일에 쓰기를 수행한다

  • 실제로 쓰기를 수행한 바이트 수를 리턴하며 오류가 발생하면 -1을 리턴함.

lseek() : 파일 오프셋 위치 지정

오프셋이란 파일의 시작 지점부터 현재 위치까지의 바이트 수
한 파일에서 파일 오프셋은 오직 하나다 !

off_t lseek(int fd, off_t offset, int whence);
//fd: 파일 기술자
//offset: 이동할 오프셋 위치
//whence: 오프셋의 기준 위치
  • 파일 시작에서 다섯 번째 위치로 이동
lseek(fd, 5, SEEK_SET);
  • 파일 끝으로 이동
lseek(fd, 0, SEEK_END);
  • 오프셋 현재 위치
cur_offset = lseek(fd, 0, SEEK_CUR);

반대방향으로 오프셋을 이동하려면 offset 값을 음수로 지정

  • 실행에 성공하면 새로운 오프셋을 리턴, 실패하면 -1을 리턴

파일 기술자 복사

dup() : 파일 기술자 복사

dup(int oldfd);

기존 파일 기술자를 인자로 받아 새로운 파일 기술자를 리턴
새로 할당되는 파일 기술자는 현재 할당할 수 있는 파일 기술자 중 가장 작은 값으로 자동 할당!

dup2() : 파일 기술자 복사

 dup2(int oldfd, int newfd);

새로운 파일 기술자를 자동으로 할당해 새로운 파일 기술자를 지정할 수 있게 해 줌
파일 기술자 oldfdnewfd로 복사


fcntl() : 파일 기술자 제어

fcntl(int fd, int cmd, ... /* arg */);

//fd: 파일 기술자
//cmd: 명령
//arg: cmd에 따라 필요시 지정하는 인자들 

파일 기술자가 가리키는 파일에 cmd로 지정한 명령을 수행


remove() : 파일 삭제

int remove(const char *pathname);

path 로 지정한 파일이나 디렉터리를 삭제한다
내부적으로 삭제 대상이 파일이면 unlink() 함수를 호출하고,
삭제 대상이 디렉터리면 rmdir()를 호출한다.

디렉터리는 비어있을 때만 삭제된다!


fsync() : 파일과 디스크 동기화 함수

int fsync(int fd);
//fd: 디스크로 저장할 파일의 파일 기술자

메모리에 위치하고 있는 파일의 내용을 디스크로 보내 메모리와 디스크의 내용을 동기화한다!
메모리의 내용이 디스크로 모두 기록되기 전에는 리턴하지 않음!


요약.

리눅스에서 파일을 읽고 쓰는 방법은 저수준(low-level) 파일 입출력고수준(high-level) 파일 입출력이 있다!

저수준(low-level) 파일 입출력

저수준 파일 입출력은 리눅스 커널의 시스템 호출을 이용해 파일 입출력을 수행함.
열린 파일을 참조할 때 파일 기술자 (file discriptor)을 사용

(장점 👍🏻)
시스템 호출을 이용하므로 파일에 빨리 접근할 수 있고,
바이트 단위로만 입출력을 수행하기 때문에 일반 파일 뿐만 아니라 특수 파일도 다룰 수 있지만,

(단점 👎🏻)
응용 프로그램을 작성할 때 바이트를 적당한 형태의 데이터로 변환 하는 여러 기능을 함수로 추가 구현해야한다는 단점이 있음.


고수준(high-level) 파일 입출력

고수준 파일 입출력은 c언어의 표준함수로 제공되며, 데이터를 바이트에 한정하지 않고 버퍼를 이용해 한꺼번에 읽기와 쓰기를 수행함.
열린 파일을 참조할 때 파일 포인터(file pointer)를 사용

profile
living Fun & Lucky
post-custom-banner

0개의 댓글