42 Born2Code/get_next_line

[get_next_line] 01 - 파일 디스크립터 (fd) / read 함수

ezn 2021. 3. 5. 00:29

파일 서술자(fd)

(파일 디스크립터1, 파일 디스크립터2)

  • 테이블 인덱스 개념
    • 0 : Standard input (stdin)
    • 1 : Standard output (stdout)
    • 2 : Standard error output (stderr)
    • 3 ~ OPEN_MAX : 파일을 불러올 때 실질적으로 부여되는 fd
  • OPEN_MAX vs. FOPEN_MAX
    • OPEN_MAX : 프로그램에 허용되는 최대 열린 파일 수를 정의하는 상수

read funtion (unistd.h)

  • open() 함수와 fopen() 함수의 차이 (read와 fread의 차이에 대해 찾아보다)
    • open() 함수는 POSIX.1 규정에 준수하는 시스템 함수이며, 커널 수준에서 동작

    • fopen() 함수는 ANSI-C 규정에 준수하는 라이브러리 함수로, 컴파일러에 의해 표준 라이브러리를 사용하여 동작하므로 어플리케이션 수준에서 동작

    • fopen() 함수는 ANSI-C 규정을 따르는 그 어떤 컴파일러에서도 사용할 수 있지만, open() 함수는 POSIX.1 규정을 따르는 운영체제에서만 사용할 수 있다. 따라서 이 둘은 기종간 이식성과 호환성에서 차이가 있음. → fopen() 함수가 조금 더 호환성이 좋다고 할 수 있다.

    • 속도, 효율에서는 대체적으로 open() 함수가 fopen() 보다 빠르다고 할 수 있다. (무조건은 아님)

      → 보통 유닉스 환경에서 fread() 나 fwrite() 같은 표준 입출력한 함수가 read(), write() 시스템콜을 사용하여 구현되었기 때문에 성능이 떨어질 거라고 생각할 수 있지만, 표준 입출력 함수는 버퍼링의 개념을 도입해서 실제 입출력 횟수를 줄임으로 성능을 높이고 있다.


#include <unistd.h>

ssize_t read (int fd, void *buf, size_t len);

/*
int fd       : 파일 디스크립터
void *buf    : 읽어 들인 바이트가 저장되는 버퍼
size_t len   : 읽어 들일 크기
return value : 읽어 들인 바이트 수, 오류 발생 시 -1
*/

 

read 함수가 여러 번 호출될 때, 읽어 들인 지점을 기억하고 있는지 테스트해 보았다.

- 테스트 대상 파일

hello
i am jin-lee
how are you?
1
2
3
4

- 테스트 코드

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define BUFF_SIZE 3

int main()
{
	int		fd;
	int		read_return;
	char	buf[BUFF_SIZE];

	read_return = 3;
	fd = open("./test", O_RDONLY);
	while (read_return == BUFF_SIZE)
	{
		read_return = read(fd, buf, BUFF_SIZE);
		printf("%s -> read:%d\n", buf, read_return);
	}

	return (0);
}

- 테스트 결과

hel -> read:3
lo
 -> read:3
i a -> read:3
m j -> read:3
in- -> read:3
lee -> read:3

ho -> read:3
w a -> read:3
re  -> read:3
you -> read:3
?
1 -> read:3

2
 -> read:3
3
4 -> read:3
3
4 -> read:0

 

호기심 천국.. 호기심 해결 → read()가 반복해서 호출될 경우, 이전 호출이 끝난 지점을 기억하고 있다.