지난 번 파일을 열었다면, 이번엔 열려있는 파일을 읽어보겠습니다.
가장 대표적인 저수준 파일 입출력에서는 POSIX에 정의된 read() 시스템 콜을 사용하여 파일을 읽어 들이는데요, 파일 오픈 시 사용했던 파일 디스크립터 기억나시나요?
fd가 참조하는 파일의 오프셋에서 len 바이트만큼 buf로 읽어 들이게 됩니다. 먼저, read() 시스템 콜의 원형과 인자를 확인해 봅시다.
#include <unistd.h> ssize_t read (int fd, void *buf, size_t len) | ||
---|---|---|
입력 인자 | int fd | open() 시스템 콜로 열린 파일을 가리키는 파일 지정 번호 |
void* buf | 파일에서 읽은 데이터를 저장할 메모리 공간 | |
len | 읽을 데이터의 크기(Byte 단위) | |
반환값 | ssize_t | 파일 읽기 성공 : 0 보다 큰 수 읽을 데이터 없을 시 : 0 (EOF : End Of File 파일의 끝을 만났을 때) |
그럼 기본적인 사용법부터 확인해보자.
간단하다. 위의 내용을 토대로 파일을 열고 buf를 읽어들이고, 출력해보는 예제이다.
출력은 아래와 같이 나오게 된다. 아래 내용은 실제 파일에 입력해 놓았던 내용이다.
read() 시스템 콜의 반환값에 대해 좀 더 자세히 알아보자. read() 시스템 콜을 사용할 때 입력인자에 해당하는 buf의 길이 len보다 작은 양수값을 반환하는 경우도 있습니다. 이러한 현상은 몇가지 경우가 있는데, len바이트 보다 적은 바이트만 사용 가능하거나, 시그널이 시스템 콜을 중단시키거나, 파이프가 깨지는 등 이유는 다양합니다.
read() 시스템 콜은 파일의 끝(EOF)를 알려주기 위해 0을 반환합니다. 파일에 읽은 바이트가 더 이상 없을 경우에 해당하며 에러로 처리되지는 않습니다. 다만, 파일을 읽을 데이터가 더 이상 없을 뿐임을 알려주는 것입니다. 하지만, 파일 끝에 도달한 것과 달리 파일에 len 바이트 만큼 읽으라고 요청하였지만 읽은 데이터가 없다면, read() 함수는 읽은 바이트가 생길 때 까지 블록된다. 이 경우는 EOF와 다릅니다. 즉, 사용 가능한 데이터가 없다는 것과 파일의 끝이라는 것은 차이가 있다. 블록되는 경우는 읽기 과정에서 더 많은 데이터를 기다림을 의미하게 됩니다. 개발을 하다보면 읽을 데이터가 없을 때 read() 시스템 콜이 블록되지 않기를 바라는 경우가 있습니다. 이러한 경우에 블록되는 대신 읽을 데이터가 없다는 사실을 살려주는 게 개발자 입장에서는 훨씬 편할 수 있죠.
즉, 읽을 데이터가 없다면 그 사실을 즉시 반환해 주면 된다는 것입니다. 이 것을 '논블록 입출력'이라 말합니다. 논블록 입출력을 이용하게 되면 특정 파일에서 블록되는 바람에 다른 파일에서 사용 가능한 데이터를 놓치거나 하는 현상을 막을 수 있죠. 그럼 논블록 입출력은 어떻게 하느냐? 지난 포스팅 참고하시면 파일 오픈시 여러 설정값을 인자로 넘겨줬었는데요, 거기에 O_NONBLOCK 도 함께 넘겨 주시면 됩니다. 논블록 모드로 열게되면 읽을 데이터가 없을 시 블록 하는 대신 01을 반환하게 됩니다.
예제 코드는 없으나 실질적으로 read() 시스템 콜을 사용하는데 그렇게 많은 어려움이 없기에, 이 정도에서 마무리하겠습니다.
'Linux > System Programming' 카테고리의 다른 글
[파일입출력] 4. 동기식 입출력 (1) | 2015.02.04 |
---|---|
[파일입출력] 3. write()로 파일에 쓰기 (2) | 2015.02.03 |
[파일입출력] 1. 파일열기 (0) | 2015.01.18 |
fork (0) | 2013.05.01 |
프로세스 생성과 종료 (0) | 2013.05.01 |