4-3 File IO - 시스템 함수 (과제-1)

7271 단어 APIAPI

File Descriptor

  • 시스템으로부터 할당 받은 파일을 대표하는 정수
  • 파일을 관리하기 위해 시스템이 필요로 하는 파일에 대한 정보를 가지고 있는 제어블록 입니다.
  • 파일마다 독립적으로 존재하며, 시스템에 따라 다른 구조를 가질 수 있씁니다.
  • 대개 보조기억장치에 저장되어 있다가 해당 파일이 Open될 때 주기억장치로 이동합니다.
  • 프로세스가 파일을 다룰 때 사용하는 개념으로, 프로세스에서 특정 파일에 접근할 때 사용하는 추상적인 값입니다.
  • 일반적으로 음이 아닌 정수를 갖습니다.
  • REG파일, DIR, 소켓, 파이프, 블록 디바이스, 캐릭터 디바이스 등 모든 객체들을 파일로 관리하는데, 프로세스가 이 파일들에 접근할 때 파일 디스크립터를 이용합니다.
  • 프로세스가 실행 중에 파일을 Open하면, 커널은 해당 프로세스의 파일 디스크립터 숫자 중 사용하지 않는 가장 작은 값을 할당해줍니다.
    • 그 다음 프로세스가 열려있는 파일에 시스템 콜을 이용해서 접근할 때, 파일 디스크립터(fd)값을 이용해서 파일을 지칭할 수 있습니다.
  • 기본적으로 할당되는 fd는 표준입력(0), 표준출력(1), 표준에러(2) 입니다.

바이너리 파일 vs 텍스트 파일

  1. 바이너리 파일
  • 데이터로 구성된 파일
  • 모든 파일은 0과 1로 이루어져 있습니다.
  • 파일 구성 형식에 특별한 조건이 없어서 대부분 데이터의 크기로 판단합니다.
  • 데이터파일(.dat), 실행파일(.exe), 이미지파일(.png), 바이너리파일(.bin) 등
  1. 텍스트 파일
  • 문자로 구성된 파일
  • 대부분 ASCII문자나 문장들로 이루어져 있습니다.
  • 소스코드파일(.cpp), README.txt 등

open()

함수 원형. int open(const char* path, int flags)
int open(const char* path, int flags, mode_t mode)
기능. 이미 존재하는 파일을 열거나, 새로운 파일을 생성하는 함수
헤더. <sys/types.h> <sys/stat.h> <fcntl.h>
매개변수1. const char* path 대상 파일 이름
매개변수2. int flags 파일에 대한 열기 옵션
매개변수3. mode_t mode O_CREAT 옵션 사용에 의해 파일이 생성될 때, 지정되는 파일 접근 권한 (예:0644, 0777)
리턴.
(성공) 파일 열기에 성공하면, 파일 디스크립터의 양의 정수값 반환
(실패) -1 errno

열기 옵션옵션 설명
O_RDONLY읽기 전용으로 열기
O_WRONLY쓰기 전용으로 열기
O_RDWR읽기와 쓰기 모두 가능
O_CREAT해당 파일이 없으면 생성
O_EXCL해당 파일이 존재하면 오류 발생 및 파일을 열지 않는다
O_TRUNC해당 파일이 존재하면 해당 파일의 모든 내용을 지운다
O_APPEND쓰기 동작 시 파일의 끝에 내용 추가
O_NOCTY열기 대상이 터미널일 경우, 이 터미널이 프로그램의 제어 터미널로 할당하지 않는다
O_NONBLOCK읽을 내용이 없을 때에는 읽을 내용이 있을 때까지 기다리지 않고 바로 복귀한다
O_SYNC쓰기 동작 시 물리적인 쓰기 동작이 완료될 때까지 대기

read()

함수 원형. ssize_t read(int fd, void* buf, size_t nbytes)
기능. open() 함수로 열기한 파일의 내용을 읽습니다
nbytes가 제로면 error
nbytes가 SSIZE_MAX보다 크면, implementation-defined
헤더. <unistd.h>
매개변수1. int fd 읽을 파일의 파일 디스크립터
매개변수2. void* buf 읽어들인 데이터를 저장할 버퍼
매개변수3. size_t nbytes 읽어들일 데이터의 최대 길이 (buf의 길이보다 길어선 안됨)
리턴.
(성공) 읽어들인 데이터 길이(바이트 수)
무조건 nbytes가 리턴되는건 아님. 중간에 파일의 끝을 만난다면 거기까지 읽기 때문.
(실패) -1 errno

write()

함수 원형. ssize_t write(int fd, const void* buf, size_t nbytes)
기능. 파일의 내용을 작성합니다
헤더. <unistd.h>
매개변수1. int fd open(), creat() 등을 통하여 정상적으로 open한 파일 디스크립터
매개변수2. const void* buf 쓰기를 할 데이터 메모리 영역
매개변수3. size_t nbytes 쓸 데이터의 사이즈
리턴.
(성공) 실제로 쓴 데이터의 byte 수 (0보다 큰 값)
count와 같은 크기의 값을 return하지만,
count보다 작은 경우에는 signal이 발생하였거나, 쓰기 공간이 부족한 경우
(0) 오류가 발생하지는 않았지만, 파일에 write되지 않음(count가 0인 경우)
(실패) -1 errno

lseek()

함수 원형. off_t lseek(int fd, off_t offset, int whence)
기능. file의 특정 위치부터 읽거나 쓰고싶을 때 유용합니다.
파일을 처음 열면 최초의 seek position은 0입니다.
open()에서 O_APPEND 플래그를 주면, 최초의 seek position은 파일의 끝에 있습니다.
헤더. <sys/types.h> <unistd.h>
매개변수1. int fd 조정할 파일의 파일 디스크립터
매개변수2. off_t offset 기준점으로부터 이동할 거리
매개변수3. int whence 기준점
SEEK_SET(0) : 파일의 시작
SEEK_CUR(1) : 현재 Seek 포인터
SEEK_END(2) : 파일의 끝
리턴.
(성공) 성공 시 위치한 Seek pointer 위치
(실패) -1 errno

lseek(fd, 10, SEEK_SET); //파일의 시작에서 10번을 건너뛴다.
lseek(fd, -8, SEEK_END); //파일의 끝에서 앞으로 8번을 건너뛴다.
lseek(fd, 5, SEEK_CUR); //현재 위치에서 다시 5번을 건너뛴다.

close()

함수 원형. int close(int fd)
기능. open() 함수로 열기한 파일을 사용 중지합니다.
헤더. <unistd.h>
매개변수. int fd 파일 디스크립터
리턴.
(성공) 0 정상적으로 close
(실패) -1

과제 - 1

my_cp 파일 복사

#include <stdio.h>
#include <errno.h>
#include <sys/types.h> //open()
#include <sys/stat.h> //open()
#include <fcntl.h> //open()
#include <unistd.h> //read() write() close()
#include <string.h> //strcmp()

enum { BUF_SIZE = 300 };

void Usage()
{
	printf("Usage: c [-f] src_file dest_file\n");
	printf("          -f: dest_file 존재시 src_file 내용으로 바꿈\n");
}

int main(int argc, char* argv[])
{
	if (argc != 3 && argc != 4) {
		Usage();
		return EIO;
	}

	if (argc == 4 && (strcmp(argv[1], "-f") != 0)) {
		Usage();
		return EIO;
	}

	int src = 0;
	int dest = 0;
	char buf[BUF_SIZE];

	int f = 0;
	if (strcmp(argv[1], "-f") == 0) {
		f = 1;
	}

	if ((src = open(argv[1 + f], O_RDWR)) == -1) {
		printf("No such file\n");
		return ENOENT;
	}

	if (f == 0) {
		if ((dest = open(argv[2 + f], O_RDWR | O_CREAT | O_EXCL, 0777)) == -1) {
			printf("Copy fail (%s existed)\n", argv[2 + f]);
			return EEXIST;
		}
	}
	else if (f == 1) {
		if ((dest = open(argv[2 + f], O_RDWR | O_CREAT | O_TRUNC, 0777)) == -1) {
			printf("Copy fail (can't access)\n");
			return EACCES;
		}
	}

	if (read(src, buf, BUF_SIZE - 1) == -1) {
		return EFAULT;
	}

	if (write(dest, buf, strlen(buf) - 1) == -1) {
		return EFAULT;
	}
	else {
		printf("Copy success!!!\n");
	}

	if (close(src) == -1) {
		return EBADF;
	}
	if (close(dest) == -1) {
		return EBADF;
	}

	return 0;
}

좋은 웹페이지 즐겨찾기