[C]저수준 파일입출력 함수(1)[fd(파일 기술자), open, close]
이 포스트는 저수준 파일입출력 함수에 관한 포스트입니다.
< 목차 >
1️. 저수준,고수준 파일 입출력함수 비교
2️. 파일 기술자 (fd, FILE Descriptor, 파일 디스크립터)
3. open함수
4. close함수
5. read함수
6. write함수
7. lseek함수
저수준 파일입출력 함수는 유닉스 기반의 고전입출력함수로 리눅스기준
<unistd.h>
헤더파일에 선언되어 있습니다.fopen(),fclose()등등...
표준입출력함수들은 버퍼를 사용하지만 저수준 파일입출력함수는 버퍼를 사용하지않는 비버퍼링 함수입니다.- 버퍼(buffer)의 사전적 의미는 어떤 장치에서 다른 장치로 데이터를 송신할 때 일어나는 시간의 차이나 데이터 흐름의 속도 차이를 조정하기 위해 일시적으로 데이터를 기억시키는 장치입니다. 저수준입출력함수는 이처럼 버퍼를 이용하지않고 파일의 바이트를 그대로 이용하기 때문에 속도가 더 빠르다는 장점이 있습니다.
- 아무래도 고전함수이기 때문에 윈도우에 넘어오면서는 달라지는 부분이 있습니다.(윈도우에서는
<io.h>
헤더파일에 선언)
함수의 특성이 이렇다보니 리눅스(유닉스)환경을 기준으로 알아볼 계획입니다.
1️⃣ 저수준,고수준 파일 입출력함수 비교
< 저수준 파일 입출력과 고수준 파일 입출력 비교 >
저수준 파일 입출력 | 고수준 파일 입출력 | |
---|---|---|
파일 지시자 | int df; | FILE* fp; |
열린 파일 참조 | 파일 기술자를 사용 | 파일 포인터를 사용 |
특징 | 1.훨씬 빠르다 2.바이트 단위로 읽고 쓴다 3.특수 파일에 대한 접근이 가능하다 4.바이트단위로 입출력을함으로 추가적인 기능을 구현해야하는 단점이 있다 (바이트를 적당한 형태의 데이터로 변환하는 함수 등) | 1.사용하기 쉽다 2.버퍼 단위로 읽고 쓴다 3.데이터의 입출력 동기화가 쉽다 4.여러가지 형식을 지원한다 |
주요 함수 | open, close, read, write, dup, dup2, fcntl, lseek, fsync | fopen, fclose, fread, fwrite, fputs, fgets, fprintf, fscanf, freopen, fseek |
- 유닉스에서 파일은 크게
일반 파일
과특수 파일
로 구분할 수 있습니다.- 일반 파일: 텍스트 바이너리 형태의 데이터를 저장하는 파일
- 특수 파일: 데이터 전송, 장치 접근에 사용하는 파일
2️⃣ 파일 기술자 (fd, FILE Descriptor, 파일 디스크립터)
- 모든 저수준 파일 입출력 함수는
파일 기술자
를 사용합니다. 파일 기술자는 현재 열려있는 파일을 구분할 목적으로 유직스가 붙여놓은 번호로 저수준 파일 입출력에서 열린파일을 참조하는 데 사용하는지시자
역할을 합니다. 파일 기술자
는 0번 부터 시작합니다. 0, 1, 2번은 기본적인 용도로 지정되어 있습니다.
파일 디스크립터(fd) | 설명 |
---|---|
0 | 표준 입력 |
1 | 표준 출력 |
2 | 표준 에러 출력 |
3 | open함수로 순차적으로 할당 |
… | ” |
10 | ” |
… | ” |
- 프로세스가 파일을
open함수
를 통해 처음 열면 3번 파일 기술자부터 순차적으로 할당됩니다.
3️⃣ open함수
- open함수는 시스템호출로, 파일을 열거나 생성 할때 사용합니다.(아래 다양한 옵션)
- 성공시 fd(파일디스크립터)를 3부터 순차적으로 (int)자료형으로 반환합니다.
- 실패시 -1을 반환합니다.
<함수원형 >
int open(const char *path, int oflag, [mode_t mode]);
< oflag >
- oflag는 함수의 작동 방식을 결정하는 옵션들입니다.
- <fcntl.h>헤더에 정의되어 있습니다.
- 옵션들은 비트 연산자 OR로 결합하여 사용할 수 있습니다.
O_RDONLY, O_WRONLY, O_RDWR
중 하나는 반드시 지정해야 합니다.
ex) `#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_EXCL )
oflag | 설명 |
---|---|
O_RDONLY | 읽기 전용으로 연다 |
O_WRONLY | 쓰기 전용으로 연다 |
O_RDWR | 읽기 및 쓰기용으로 연다 |
O_APPEND | 파일 기록 시 내용을 파일의 끝에 추가한다 |
O_CREAT | 파일이 존재하지 않으면 새로 생성한다 셋쨰 인수 mode도 지정해야된다 |
O_EXCL | O_CREAT와 이 옵션을 함께 지정하면 파일이 이미 존재하는 경우에 오류가 발생한다 |
O_TRUNC | 이미 존재하는 파일을 읽기 또는 쓰기 모드로 열었을 때 파일의 크기가 0으로 잘라버린다 |
O_NOCTTY | 열려 있는 장치가 컨트롤링 터미널이 되지 못하도록 한다 |
O_NONBLOCK | 즉시 리턴될 것인지 아니면 장치가 준비될 때까지 블록될 것인지 제어한다 |
< mode(파일 권한을 설정) >
- <sys/stat.h>헤더에 선언되어 있습니다.
소유자|그룹|기타 사용자|
를r(읽기)|w(쓰기)|x(실행)
를 8진수 단위씩 나눠서 지정할 수 있습니다.
예를 들어rwxrwxrwx
(모든권한허용) =111111111
일경우 8진수 표기법으로0777
로 작성할 수 있습니다.- 뿐만아니라 다음과 같이 매크로로 선언되어있는 mode명을 직접 작성해도 됩니다.
mode | 설명 |
---|---|
S_IRWXU | 0700, 파일소유자에게 읽기, 쓰기, 실행권한 부여 |
S_IRUSR | 0400, 사용자에게 읽기 권한 부여 |
S_IWUSR | 0200, 사용자에게 쓰기 권한 부여 |
S_IXUSR | 0100, 사용자에게 실행 권한 부여 |
S_IRWXG | 0700, 그룹에게 읽기, 쓰기, 실행권한 부여 |
S_IRGRP | 0400, 그룹에게 읽기 권한 부여 |
S_IWGRP | 0200, 그룹에게 쓰기 권한 부여 |
S_IXGRP | 0100, 그룹에게 실행 권한 부여 |
S_IRWXO | 0700, 기타 사용자에게 읽기, 쓰기, 실행권한 부여 |
S_IROTH | 0400, 기타 사용자에게 읽기 권한 부여 |
S_IWOTH | 0200, 기타 사용자에게 쓰기 권한 부여 |
S_IXOTH | 0100, 기타 사용자에게 실행 권한 부여 |
< open함수 예시 >
#include <sys/stat.h> // mode_t형식자
#include <fcntl.h> // oflag 옵션,mode 옵션
#include <unistd.h> // 저수준함수 open(),close()함수
#include <stdio.h> // perror()함수
#include <stdlib.h> // exit()함수
int main(void)
{
int fd;
mode_t mode; // 윈도우에서는 mode_t형식자가 없다..
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; //"0644"와 같다.윈도우에서는 이런 mode플래그가 없는듯하다..
fd = open("unix.txt", O_CREAT, mode);
if (fd == -1) // open에 실패할시 -1을 반환한다
{
perror("CREAT\n"); // 오류코드를 해석해서 stderr스트림으로 출력해주는 함수이다.
exit(1); // 에러코드 1을 반환하고 프로그램을 정리하고 종료합니다.
}
close(fd); // 파일을 열었으면 꼭 닫아줍니다.
return (0);
}
- open함수도 파일입출력함수처럼 에러시에는
errno
값이 자동으로 설정됩니다. 그렇기 때문에perror함수
로 오류코드를 해석할 수 있습니다. open함수
로 파일을 열었으면 반드시close함수
로 파일을 닫아주어야 합니다.
4️⃣ close함수
<함수원형 >
int close(int fd);
- 파일 입출력 작업을 모두 완료하면 반드시 파일을 닫아야 합니다.
- 성공적으로 닫으면 0을 반환하고 실패시 -1을 반환합니다.
(오류코드를 외부 변수 errno에 저장합니다.)