UNIX file 접근 Primitives
File은 byte들의 linear sequence이다.
파일 입출력은 두가지로 나눌 수 있다.
- 저수준 파일 입출력 (open, close, read, write, dup, dup2, fcntl ...)
- 고수준 파일 입출력 (fopen, fclose, fread, fwrite, fputs ...)
저수준 파일 입출력
저수준 파일 입출력은 system call을 통해 파일 입출력을 수행한다.
- 장점
- system call을 이용하여 빠르게 접근 가능
- byte 단위로 입출력을 수행하므로 특수 파일도 다를 수 있다.
- 단점
- byte를 적당한 형태의 데이터로 변환해야 한다.
고수준 파일 입출력
c언어의 표준함수로 제공되며, 데이터를 byte에 한정하지 않고 버퍼를 이용해 한꺼번에 읽기와 쓰기를 수행한다.
file descriptor
file descrpitor는 현재 open된 file을 구분할 목적으로 UNIX가 붙여 놓은 번호이다.
표준 입출력
- 0 : 표준 입력
- 1 : 표준 출력
- 2 : 표준 오류 출력
한 프로세스가 동시에 open할 수 있는 file의 개수에는 제한이 있으므로 close를 사용하여 닫아주어야 한다.
open 시스템 호출
기존의 file을 ipen하거나, 새롭게 file을 생성하여 open하는 system call이다.
사용법
#include <sys/types.h>
#Include <sys/stat.h>
#include <fcntl.h>
int open(const char *filename, int oflag, [mode_t mode]);
- filename : 파일 이름
- oflag : file을 access 또는 create하는 방식
- O_RDONLY, O_WRONLY, O_RDWR
- O_CREAT, O_EXCL, O_TRUNC
- O_APPEND
- mode : file을 새로 생성할 때만 사용
- return 값 : 실행 성공 시 file descriptor; 실행 실패 시 -1;
creat 시스템 호출
file을 생성하여 open하거나, 기존 file을 open하는 system call
사용법
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int creat (const char *filename, mode_t mode);
주의사항
- file을 쓰기 가능한 상태로 open해야한다.
- file이 이미 존재하면, 두 번째 인자는 무시하고 기존 file은 0으로 open한다.
close 시스템 호출
open된 file을 close할 때 사용
process 종료 시, open된 file들은 자동으로 close된다. 그러나, 동시에 open할 수 있는 file 수 제한 때문에 close 사용한다.
사용법
#include <unistd.h>
int close(int filedes);
- filedes : open된 file의 file descriptor
- return 값 : 성공 시 0; 실패 시 -1;
read 시스템 호출
open된 file로부터 지정한 byte수 만큼의 data를 읽어 지정된 저장장소에 저장하는 명령이다.
file pointer 또는 read-write pointer가 읽혀질 다음 byte의 위치를 나타낸다.
사용법
#include <unistd.h>
ssize_t read(int filedes, void *buffer, size_t nbytes);
- filedes : open된 file의 file descriptor
- *buffer : 읽은 data를 저장할 곳의 주소(data type은 상관 없음)
- nbytes : 읽을 byte 수 (data type에 상관없이 지정된 byte 수 만큼 읽는다.)
- return 값 : 성공 시, 실제 읽힌 byte 수; 실패 시 -1;
- return 값 < nbytes면, file에 남은 data가 nbytes 보다 적을 때
그 다음 더 이상 읽을게 없으면; return 값은 0;
write 시스템 호출
지정된 저장장소에서 지정한 byte수 만큼의 data를 읽어 open된 file에 쓰는 명령
read와 마찬가지로 file pointer or read-write pointer가 쓰여질 다음 byte의 위치를 나타낸다.
사용법
#include <unistd.h>
ssize_t write(int filedes, const void *buffer, size_t nbytes);
- filedes : write를 할 file의 descriptor;
- *buffer : write할 내용이 들어 있는 저장 장소의 주소
- nbytes : write할 byte의 수;
- return 값 : 쓰여진 byte 수 or -1;
- 보통은 return 값 = n
- return 값 < n이면, 쓰는 도중 media가 full
- 만약, 쓰기 전에 꽉 차면, -1 return
주의사항
기존 file을 open system call로 open하고 바로 write를 하면, 파일의 처음 부터 쓰여진다.
fd = open("data", O_WRONLY|O_APPEND); // open하자마자, file pointer가 file의 끝으로 이동
read/write의 효율성
- BUFSIZE가 512(disk blocking factor)의 배수일 때, 효율적이다.
- system call의 수가 적을수록 효율적이다.
lseek와 임의 접근
open된 file내의 특정 위치로 file pointer를 이동시키는 system call
사용법
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
- filedes : open된 file의 file descriptor
- whence : whence에서 offset만큼 떨어진 위치로 이동
- SEEK_SET : file의 시작 지점
- SEEK_CUR : 현재 file 위치
- SEEK_END : file의 끝 지점
- offset : whence에서 offset만큼 떨어진 위치로 이동
- return 값 : 이동된 위치, 실패 시 -1
file의 제거
file을 삭제하는 명령
사용법
#include <unistd.h>
int unlink(const char *filename);
#include <stdio.h>
int remove(const char *filename);
주의사항
- include file이 다르다.
- file descriptor가 아니라, file 이름을 쓴다.
- 성공 시 0, 실패 시 -1 return
- file이 open되어 있는 상태라면, 실행되지만 프로그램 종료 후 삭제되어 있다.
- 차이점
unlink는 file만 삭제, remove는 file과 빈 directory도 삭제