본문 바로가기

STUDY/linux

File I/O system call in LINUX

UNIX 계열 운영체제에서 파일의 종류는 크게 두 종류이다.

하나는 regular file, 우리가 흔힌 생각하는 파일이다. 예를 들면 txt, c, cpp 등등

또 다른 하나는 I/O device를 file 로 추상화한 special file이다.

 

이러한 파일에 데이터를 읽고 쓰는 read, write와 같은 함수들은 우리가 흔히 "비싼" 함수라고 한다.

그렇다면 이 함수들은 왜 비싼 함수라고 불릴까?

 

바로 이러한 입출력 함수들은 운영체제를 거쳐 실행되기 때문이다.

이렇게 운영체제에 도움을 요청하는 함수를 system call이라고 한다.

linux에서 제공해주는 file i/o를 위한 system call을 알아보자

이번 함수의 기준은 man page를 기준으로 작성하였다.

 

다음은 가장 많이 쓰이는 i/o를 위한 system call이다.

 

  • open
  • read
  • write
  • close
  • lseek

이러한 함수들은 파라미터에 파일 디스크립터를 포함한다.

파일 디스크립터는 해당 프로세스의 open file을 관리하기 위한 구조체 배열이다. 즉 열려있는 파일을 참조할 때 사용한다.

파일 디스크립터는 숫자이지만 0~2번까지는 시스템 상에서 미리 정의되어 있다.

 

#include <unistd.h>

0 => STDIN_FILENO: 표준 입력

1 => STDOUT_FILENO: 표준 출력

2 => STDERR_FILENO: 표준 에러

 


파일 오픈 함수

 

#include <fcntl.h>

int open(char *filename, int flag..., [mode_t mode])

 

함수 명세

return 파일 디스크립터(file descriptor), 실패 시 -1
description 파일을 연다.

 

파라미터

char *filename 파일 명
int flag 파일을 열때의 option
mode (선택 사항) 권한

 

이때 두번 째 파라미터로 설정 가능한 flag는 다음과 같다.

 

  • O_RDONLY:  읽기 전용
  • O_WRONLY:  쓰기 전용
  • O_RDWR:      읽기, 쓰기 모두 가능
  • O_APPEND:  파일 끝에 추가
  • O_CREAT:     해당 파일이 존재하지 않을 시 새로 생성 (이 옵션은 파일 권한이 필요, 즉 mode 파라미터가 필수)
  • O_EXCL
  • O_TRUNC:    파일 내용 삭제
  • O_NONBLOCK
  • O_SYNC

파일 닫기 함수

 

#include <unistd.h>

int close(int fd)

 

함수 명세

return 성공 시 0, 실패 시 -1
description 파라미터로 들어오는 파일 디스크립터로 파일을 닫는다.

 

파라미터

int fd 닫고자 하는 파일의 파일 디스크립터

파일 읽기 함수

 

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t nbytes)

 

함수 명세

return 읽어온 bytes 수, 파일을 다 읽은 경우 0, 실패 시 -1
description 파일을 읽어서 버퍼에 저장한다.

 

파라미터

int fd 파일 디스크립터
void *buf 파일에서 읽어서 저장할 버퍼
size_t nbytes 읽기 가능한 최대 byte 수

 


파일 쓰기 함수

 

#include <unistd.h>

ssize_t write(int fd, void *buf, size_t nbytes)

 

함수 명세

return 실제로 파일에 쓴 bytes 수, 실패 시 -1
description 파일에 버퍼의 내용을 쓴다.

 

파라미터

int fd 파일 디스크립터
void *buf 파일에 쓸 내용 (포인터 변수)
size_t nbytes 파일에 쓰는 byte 수

 


파일 포인터의 위치 조정 함수

 

#include <unistd.h>

int lseek(int fd, off_t offset, int whence)

 

함수 명세

return 옮겨진 파일 포인터의 위치
description whence에서 파일 포인터의 위치를 offset 만큼 옮긴다.

 

파라미터

int fd 파일 디스크립터
off_t offset 파일 포인터를 옮길 offset (얼마나 옮길지)
int whence 어디서 부터 파일 포인터를 옮길지에 대한 기준점

 

이때 세 번째 파라미터로 들어가는 기준점은 다음과 같은 매크로를 사용 가능하다.

 

  • SEEK_SET(0) : 맨 앞
  • SEEK_CUR(1) : 현재 위치
  • SEEK_END(2) : 맨 끝

예를 들어 파일 포인터를 제일 앞에서 10만큼 옮기고 싶다면

 

lseek(fd, 10, SEEK_SET)

 

위와 같이 쓰는 것이다.

 


파일 생성 함수

 

#include <fcntl.h>

int creat(char *filename, mode_t mode)

 

함수 명세

return 새로 생성한 파일의 파일 디스크립터 (fd), 실패 시 -1
description mode 권한을 부여하여 새로운 파일을 생성한다.

이때 함수의 파일 디스크립터는 write-only로 열리게 된다.

 

파라미터

char *filename 생성 할 파일 명
mode_t mode 새로운 파일에 부여할 권한

 

이 때 세 번째 인자의 권한이란 linux file에서의 사용자 마다 부여되는 read, write, execute 권한을 의미한다.

이 함수의 특징은 open() 함수로도 똑같은 동작을 할 수 있다는 것이다.

 

다음과 같이 open 함수의 flag를 설정하면 create 함수와 똑같이 동작한다.

 

open("example.txt", O_WRONLY|O_CREAT|O_TRUNC, 755)

example

linux shell command 중에 cp는 파일을 복사해준다.

이 cp 명령어를 구현해보자

 

open 함수로 두개 파일을 연다. 이때 세번째 인자로 들어오는 파일 명은 새로 생성해야 하는 파일이므로

open 함수의 flag를 설정하여 생성하였다.

 

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{
	int		fd1, fd2;
	char	buf[1024];

	if (argc != 3)
		exit(1);

	fd1 = open(argv[1], O_RDONLY);
	if (fd1 < 0)
		exit(1);

	fd2 = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0755);
	if (fd2 < 0)
		exit(1);

	while ((count = read(fd1, buf, 1)) > 0)
		write(fd2, buf, count);
	
	close(fd1);
	close(fd2);
}

 

그 후 while 문을 돌면서 fd1에서 1글자씩 읽어서 버퍼에 저장하고, 다시 fd2에 버퍼의 내용을 읽은 만큼 즉 count 만큼 씀으로 써 복사가 이루어진다.

마지막에는 close를 통해 파일을 닫아주면 함수가 끝나게 된다.

'STUDY > linux' 카테고리의 다른 글

Files and Directories in LINUX  (0) 2022.03.31
SIGNAL in LINUX  (0) 2022.03.29
Process and Threads in LINUX  (0) 2022.03.28
File I/O functions in C Library  (0) 2022.03.23
shell commands  (0) 2022.01.04