read(2)

#include <unistd.h>

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

open(2), creat(2), socket(2), accept(2) 등으로 생성한 file descriptor로 부터 데이터를 읽습니다. 파일을 읽으면 읽은 size만큼 파일의 다음 읽을 위치가 이동됩니다. 읽을 위치가 파일의 끝에 도달하면 더 이상 읽을 데이터가 없으므로 0을 return합니다.

 

 

파라미터

fd
    -  open(2), creat(2), socket(2), accept(2) 등을 통하여 정상적으로 open한 file descriptor
buf
    - 읽을 데이터를 저장할 메모리 영역(buffer)
count
    - 읽을 size (byte 수)

 

RETURN

0보다 큰 수
    - 실제로 읽은 데이터 byte 수.
    - 일반적으로 count와 같은 값을 return하지만, count보다 작은 경우에는 end of file에 도달하였거나, 
      socket통신에서는 수신할 데이터가 아직 도착하지 않은 경우나
      peer(상대)에서 socket을 close했을 때입니다.


0
    - end of file에 도달하여 더 이상 읽을 자료가 없는 경우


-1
    - 오류가 발생한 경우이며 상세한 오류는 errno에 설정됩니다.

 EAGAIN : file을 open할 때에 O_NONBLOCK flag이 설정되었으며, 
              현재 읽을 데이터가 없어서 read()함수를 바로 return함.
 EAGAIN or EWOULDBLOCK : fd가 socket이고 socket에 O_NONBLOCK으로 설정된 경우 
              읽을 데이터를 수신하지 못하여 바로 return함.
 EBADF :  fd가 유효하지 않은 file descriptor임.
 EFAULT : buf가 access할 수 없는 영역의 데이터 buffer임. 
             주로 변수를 pointer로 설정한 후에 malloc(3)하지 않은 경우
 EINTR : signal이 발생하여 interrupt됨.
 EINVAL : fd, buf, count 등의 변수가 잘못 설정된 경우. (예, count가 -값이 설정된 경우 등)
 EIO : I/O 오류. background process에서 terminal에 대한 I/O를 시도했다든 지...
 EISDIR : open된 fd가 directory인 경우

 


활용 예제

 

Sample. 파일 backup 

#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

/*
* 읽을 데이터를 요청한 사이즈 만큼 읽어들임.
* 파일의 끝이면 요청한 사이즈보다 작을 수 있음.
* Signal이 발생하더라도 읽기를 처리함.
*/
int read_data(int fd, char *buffer, int buf_size)
{
    int size = 0;
    int len;

    while(1) {
        if((len = read(fd, &buffer[size], buf_size - size)) > 0) {
            size += len;
            if(size == buf_size) {
                return size;
            }
        } else if(len == 0) {
            return size;
        } else {
            if(errno == EINTR) {
                continue;
            } else {
                return -1;
            }
        }
    }
}
 
/*
* 저장할 데이터를 요청한 사이즈 만큼 write함
* signal이 발생하더라도 저장함
*/
int write_data(int fd, const char *buffer, int buf_size)
{
    int size = 0;
    int len;
 
    while(1) {
        if((len = write(fd, &buffer[size], buf_size - size)) > 0) {
            size += len;
            if(size == buf_size) {
                return size;
            }
        } else if(len == 0) {
            return size;
        } else {
            if(errno == EINTR) {
                continue;
            } else {
                return -1;
            }
        }
    }
}

int main(int argc, char *argv[])
{
    int  rfd;
    int  wfd;
    int  len;
    char buffer[4096];
 
    /* 파일을 읽기 전용으로 open함 */
    if((rfd = open("sample.txt", O_RDONLY)) == -1) {
        fprintf(stderr, "FILE READ OPEN ERROR: %s\n", strerror(errno));
        return 1;
    }
 
    /* 쓰기 전용으로, 파일이 없으면 생성하고, 파일이 있으면 전체데이터를 삭제하고 open함 */
    if((wfd = open("sample.txt.bak", O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) {
        fprintf(stderr, "FILE WRITE OPEN ERROR: %s\n", strerror(errno));
        return 1;
    }
 
    while(1) {
        if((len = read_data(rfd, buffer, 4096)) == -1) {
            fprintf(stderr, "READ ERROR: %s\n", strerror(errno));
            return 1;
        }
        if(len == 0) {
            break;
        }
        if((len = write_data(wfd, buffer, len)) == -1) {
            fprintf(stderr, "WRITE ERROR: %s\n", strerror(errno));
            return 1;
        }
    }
 
    close(rfd);
    close(wfd);
 
    return 0;
}

 


see also: System Call File I/O Library

 

 

블로그 이미지

사용자 자연&사람

행복한 개발자 programmer since 1995.

댓글을 달아 주세요