[Linux] 파일 입출력 System call 함수
- [ CS기초 ]/Linux
- 2022. 3. 14.
FDT, FT, IT
- FDT(파일디스크립터 테이블) : 프로세스마다 한개씩 가지고있음. 0:stdin, 1:stdout, 2:stderr로 자동할당, 3부터 파일 open시 할당된다. 파일을 시스템 프로그래밍 차원에서 바이트단위의 입출력으로 다룰 수 있게 한다.
- FT(파일 테이블) : 모든 프로세서가 오픈한 파일에 대한 참조. 파일디스크립터 테이블에서 참조하는 수
- IT(아이노드 테이블)
open(2)
파일을 열거나 생성할 때 사용하는 system call 함수
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
int open(const char* pathname, int oflag);
int open(const char* pathname, int oflag, mode_t mode);
@param pathname: 열거나 생성할 파일명(경로)
@param oflag: open할 파일의 특성 결정. 어떤 용도로 사용할지 결정
@param mode: 파일의 읽기/쓰기/실행 권한을 지정
@return: 파일에 대한 올바른 접근인지 확인한 후 파일 디스크립터 리턴
파일 접근 모드 플래그
O_RDONLY / O_WRONLY / O_RDWR : 파일을 읽기/쓰기/읽고쓰기 전체의 권한으로 오픈 > 셋 중 하나 사용가능
O_APPEND : 파일에 IO시 오프셋을 자동으로 파일 맨 끝으로 이동 (내용 추가)
O_CREAT : 파일이 존재하지 않을 경우 생성
O_EXCL : CREAT옵션과 함께 사용, 파일이 이미 존재하면 에러 리턴
O_TRUNC : 파일이 이미 존재할 경우 덮어쓰기
creat()
파일 생성시 사용하는 시스템 호출함수. 다만 open함수에 O_CREAT 옵션을 주면 되기때문에 잘 사용하지는 않는다.
#include<sys/stat.h>
#include<sys./types.h>
#include<fcntl.h>
int creat(const char* pathname, mode_t mode);
상태 플래그를 사용하지 않는다는 점만 제외하면 open(2)과 동일하다.
open(pathname, O_WRONLY|O_CREAT|O_TRUNC, mode);
open(pathname, O_RDWR|O_CREAT|O_TRUNC, mode);
쓰기 기능이 들어가도록("w"나 "w+") 상태플래그를 주면 된다.
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
int main() {
char* fname = "ssu_test.txt";
int fd;
if((fd=creat(fname, 0666))<0) {
fprintf(stderr, "creat error for %s\n", fname);
exit(1);
}
else {
printf("Success!\nFilename : %s\nDescripter : %d\n", fname, fd);
close(fd);
}
exit(0);
}
> creat()함수를 통해서 파일을 열고 디스크립터를 출력하는 예제.
creat의 mode값으로 0666이 들어간것은 rw-rw-rw-을 의미한다. (4-2-1)
#include<stdio.h>
#include<fcntl.h>
#include<stdlib.h>
#include<unistd.h>
int main() {
char* fname = "ssu_test.txt";
int fd;
if((fd = creat(fname, 0666))<0) {
fprintf(stderr, "creat error for %s\n", fname);
exit(1);
}
else {
close(fd);
fd = open(fname, O_RDWR);
printf("Succeeded!\n<%s> is new readable and writable\n", fname);
}
exit(0);
}
> close()했다가 다시 open해도 문제가 발생하지 않는다. (단지 새로운 파일디스크립터값을 할당받을것임)
lseek()
파일을 오픈한 뒤 offset의 위치를 명시적으로 변경하는 시스템 호출함수이다. offset의 위치만 변경하고 리턴해줄 뿐 I/O는 일어나지 않는다.
#include<sys/types.h>
#include<unistd.h>
off_t lseek(int filedes, off_t offset, int whence);
@param filedes: 대상 파일 디스크립터 번호
@param offset: 변경할 바이트 수
@param whence: 기준 오프셋 (SEEK_SET, SEEK_CUR, SEEK_END)
@return off_t: 정수(integer)형. 새 파일 오프셋을 리턴한다. 정규 파일이 아닌경우 lseek이 불가하므로 -1을 리턴한다.
SEEK_SET : 파일의 오프셋 위치를 파일의 처음으로 지정. 처음부터 입출력을 하려면 offset인자를 0으로 지정해주면 됨
SEEK_CUR : 파일의 오프셋 위치를 현재 오프셋 위치에 offset인자만큼 더한 값으로 설정. 현재 오프셋 위치를 알려면 offset인자를 0으로 지정해주면 됨
SEEK_END : 파일의 오프셋 위치를 파일 크기 다음으로 지정. 파일의 끝에 새로운 데이터를 추가하려고 하면 이 값과 함께 offset인자를 0으로 지정하면 됨
ㆍ파일 오프셋(offset)이란 파일의 어느 부분을 읽는지를 의미한다. 오프셋 값은 O_APPEND 상태 플래그가 적용되어 있으면 파일의 끝, 적용되어 있지 않으면 항상 0을 기본값으로 갖는다.
ㆍ오프셋이 파일의 실제 크기보다 클 경우, 그만큼 파일의 크기가 증가한다.
예제
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
int main() {
char* fname = "ssu_test.txt";
off_t fsize;
int fd;
if((fd = open(fname, O_RDONLY))<0) {
fprintf(stderr, "open error for %s\n", fname);
exit(1);
}
if((fsize = lseek(fd,(off_t)0,SEEK_END)) < 0) {
fprintf(stderr, "lseek error\n");
exit(1);
}
printf("The size of <%s> is %ld bytes.\n", fname, fsize);
exit(0);
}
> lseek함수과 SEEK_END를 통해서 파일의 바이트 수를 구하는 예제
read()
open상태의 파일에서 데이터를 읽을 때 사용하는 시스템 호출함수. 읽기 전용("r") 혹은 읽기쓰기모드("r+")로 오픈된 파일로부터 지정된 메모리로 nbytes만큼의 데이터를 읽음
#include<unistd.h>
ssize_t read(int filedes, void* buf, size_t nbytes);
@param filedes: 오픈된 파일 디스크립터
@param buf: 파일을 읽어들일 버퍼
@param nbytes: 읽을 메모리 바이트수
@return: 실제로 읽은 바이트 수(integer)(파일의 끝을 읽을 경우 중단되기 때문에 요청한 바이트 nbytes보다 작을 수 있음), 파일의 오프셋 위치도 읽은 바이트수만큼 이동된다.
'[ CS기초 ] > Linux' 카테고리의 다른 글
[Linux] fork(), wait(), exec() (0) | 2022.04.17 |
---|---|
[Linux] C 표준 입출력 라이브러리 함수(2) (0) | 2022.04.14 |
[Linux] C 표준 입출력 라이브러리 함수 (1) (0) | 2022.03.13 |