티스토리 뷰
틀린 내용이 있다면 댓글로 알려주세요! 감사합니다 :)
함수들에 공부하기 전 사전지식
- 함수들에 공부하기에 앞서
파일디스크립터
라는 개념을 먼저 이해하고 있으면 좋다.
파일 디스크립터(File Descriptor)란?
리눅스와 유닉스에서는 시스템을 전부 파일로 처리하여 관리한다. (하드웨어 등 모든 장치도 포함)
시스템에서 프로세스가 파일에 접근하기 위한 방법으로 파일 디스크립터(FIle Descriptor)라는 핸들이 필요하다.
해당 파일을 open할때( 해당파일에 접근할 때 ) 파일 디스크립터는 0부터 N까지 즉, 음수가 아닌 0부터 차례대로 숫자를 부여받으며, 0, 1, 2는 프로세스가 메모리에서 실행을 시작할때 기본적으로 할당되는 파일 디스크립터이다.
기본적으로 할당받는 파일 디스크립터
0번 : 표준 입력(Standard Input) / STDIN_FILENO
1번 : 표준 출력(Standard Output) / STDOUT_FILENO
2번 : 표준 에러(Standard Error) / STDERR_FILENO
그러므로 우리가 생성하는 파일 디스크립터들은 3번 부터 차례대로 할당받게된다. 쉽게 생각하면, 파일 디스크립터는 파일을 다루기 위해서 해당파일의 주소를 참조하여 접근하는 형태라고 생각하면 된다.
이 fd를 활용해서 파일을 읽을수가 있다. 바로 read, open, close 함수를 이용하는 것이다.
FD의 최대값은 OPEN_MAX라는 값이다.
즉, 하나의 프로세스 당 최대 OPEN_MAX개의 파일을 열 수 있다. OPEN_MAX 값은 플랫폼에 따라 다르다.
최대 파일 갯수는 다음의 방법을 사용하여 알아볼 수 있다. 내 환경에서는 4096개의 값이 나왔다.
방법 1) 터미널에서 getconf 명령어로 확인
getconf OPEN_MAX
/*결과값*/
4096
파일 디스크립터가 단순히 숫자인 이유는 프로세스가 유지하고 있는 file descriptors 테이블의 인덱스이기 때문이다.
파일 오픈 or 소켓생성 시 부여되는 파일 디스크립터는 3부터 시작한다.
프로세스가 실행 중에 파일을 Open 하면 커널은 해당 프로세스의 파일 디스크립터 숫자 중에 사용하지 않는 가장 작은 값을 할당해 준다.
그 다음 프로세스가 열려있는 파일에 시스템 콜을 이용해서 접근할 때, 파일 디스크립터 값을 이용해 파일을 지칭할 수 있다.
사진 출처 https://dev-ahn.tistory.com/96
file descriptors 테이블의 각 항목은 FD 플래그와 파일 테이블로의 포인터를 가지고 있다.
이 포인터를 이용하여 FD 를 통해 시스템의 파일을 참조 할 수 있는 것이다.
프로세스는 이런 FD 테이블과 파일 테이블의 정보를 직접 고칠 수 없으며, 반드시 커널을 통해서 수정을 해야 한다.
💡 open함수에 대하여
fcntl.h
헤더에 포함 되어 있는 함수
Prototype
ssize_t open(const char *pathname, int flags);
-
pathname
: 파일의 경로와 이름으로, 절대경로의 파일명과 상대경로의 파일명 모두 허용. -
flags
: 파일을 어떻게 열지를 결정하는 플래그, 읽기전용으로 열때는 O_RDONLY, 쓰기 전용으로 열때는 O_WRONLY, 읽기 쓰기로 열고싶을때는 O_RDWR을 사용한다.
Return Value
- 성공적으로 파일을 열게 되면 파일 디스크립터를 반환한다. 그렇지 않으면 음수를 반환한다. open이 제대로 되었는지 확인하기 위해서는 int형 변수를 하나 선언해준 후, open의 결과값이 0 미만인지 확인한다.
💡 close함수에 대하여
unistd.h
헤더에 포함 되어 있는 함수
Prototype
ssize_t close(int fd);
fd
: open하고 있는 프로세스를 닫을 fd를 인자로 받는다.
Return Value
- 정상적으로 close했다면 0을, 실패했다면 -1을 반환한다.
💡 read 에 대하여
unistd.h
헤더에 포함 되어 있는 함수
Prototype
ssize_t read (int fd, void *buf, size_t nbytes)
-
fd
: 파일 디스크립터 -
buf
: 파일을 읽어 들일 버퍼 -
nbytes
: 버퍼의 크기
Return Value
- 정상적으로 실행되었다면 읽어들인
바이트 수
를, 실패했다면-1
을 반환한다.
read 함수의 예제
- 예제에 사용될 test.txt의 내용
#test.txt
12345
ABCDE
abcde
67890
#include <stdio.h> // puts()에 필요한 헤더
#include <string.h> // strlen()
#include <fcntl.h> // O_WRONLY , open함수를 쓰기 위한 헤더
#include <unistd.h> // write(), close()
#define BUFF_SIZE 1024
int main()
{
char buff[BUFF_SIZE];
int fd;
if ( 0 < ( fd = open( "./test.txt", O_RDONLY)))
{
read( fd, buff, BUFF_SIZE);
puts( buff);
close( fd);
}
else
{
printf( "파일 열기에 실패했습니다.\n");
}
return 0;
}
- 위와 같이 실행이 된다면 결과는 아래와 같이 나온다.
$ ./a.out
12345
ABCDE
abcde
67890
$
하지만 만약에 buff의 크기를 벗어나게 된다면, 여러번 읽기를 시도할 수 있다.
#include <stdio.h> // puts()에 필요한 헤더
#include <string.h> // strlen()
#include <fcntl.h> // O_WRONLY , open함수를 쓰기 위한 헤더
#include <unistd.h> // write(), close()
#define BUFF_SIZE 5 // 버퍼의 크기가 작습니다.
int main()
{
char buff[BUFF_SIZE];
int fd;
size_t rd_size;
if ( 0 < ( fd = open( "./test.txt", O_RDONLY)))
{
while( 0 < ( rd_size = read( fd, buff, BUFF_SIZE-1))) // 4 byte씩 읽씁니다.
{
buff[rd_size] = '\0'; // puts()를 위해 NULL을 대입
puts( buff);
}
close( fd);
}
else
{
printf( "파일 열기에 실패했습니다.\n");
}
return 0;
}
-
puts함수에 대해서 궁금하다면 여기를 참고하세요!
-
그러면 아래와 같이 4byte씩을 읽은 결과가 나오게 됩니다.
$ ./a.out
1234
5
AB
CDE
abcd
e
67
890
$
📕 reference :
'TIL(Today I Learn) > C++' 카테고리의 다른 글
vector를 쓰는 이유(2021.03.29 업데이트) (0) | 2021.02.18 |
---|---|
lst함수들에 대해서(lstnew, lstadd_front, lstadd_back, lst_size) (2) | 2021.01.17 |
fd 출력함수들에 대해서 (putchar, putstr, putendl, putnbr) (0) | 2021.01.14 |
atoi 함수 구현(2021.03.03 업데이트) (0) | 2021.01.07 |
is함수들 구현 (isalpha, isdigit, isascii, isalnum, isspace) (0) | 2021.01.07 |
- Total
- Today
- Yesterday
- 백준
- 알고리즘
- html
- JavaScript
- c언어알고리즘
- vscode
- HEXO
- C언어 문제
- C언어문제
- 프로그래머스 카카오
- JS
- 42서울
- 42서울 합격
- C언어
- Git
- windows 10 ubuntu
- 42seoul
- 자바스크립트
- React
- 프로그래머스 코테
- 프로그래머스 코딩테스트
- 프로그래머스 자바
- css
- vscode commit vi
- c언어 함수
- 마크다운 이미지 업로드
- git vi
- 42서울 합격 후기
- flexbox
- 42서울 라피신
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |