벡터 입출력

벡터 입출력은 한번의 시스템 콜을 사용해서 여러 개의 버퍼 벡터에 쓰거나 여러 개의 버퍼 벡터로 읽어 들일 때 사용하는 입출력 메서드다. 벡터 입출력은 선형 입출력 메서드에 비해 다음과 같은 장점을 가지고 있다.

  • 데이터가 자연스럽게 분리되어 있다면 직관적인 방법으로 조작할 수 있다.
  • 하나의 벡터 입출력 연산은 여러 번의 선형 입출력 연산을 대체할 수 있다.
  • 시스템 콜의 호출 횟수를 줄여줄 뿐만 아니라 내부적으로 선형 입출력 구현에 비해 좀 더 최적화된 구현을 제공한다.
  • 여러 번의 선형 입출력 연산과는 대조적으로 벡터 입출력 연산 중에 다른 프로세스가 끼어들 여지가 없다.

readv()와 writev()

#include <sys/uio.h>

ssize_t readv (int fd, const struct iovec *iov, int count);

ssize_t writev (int fd, const struct iovec *iov, int count);
  • readv() 함수는 파일 디스크럽터 fd에서 버퍼에 있는 데이터를 읽어서 count 개수만큼 iov 버퍼에 저장한다.
  • writev() 함수는 count 개수만큼의 iov 버퍼에 있는 데이터를 파일 디스크립터 fd에 기록한다.

iovec 구조체

iovec 구조체는 세그먼트라고 하는 독립적으로 분리된 버퍼를 나타낸다. readv()와 writev() 함수 모두 iov[0]부터 시작해서 iov[count-1]까지 세그먼트 순서대로 동작한다.

#include <sys/uio.h>

struct iovec {
	void *iov_base; // 버퍼의 시작 포인터
    size_t iov_len // 버퍼 크기 (바이트)

반환값

readv()와 writev()는 호출이 성공했을 때 일걱나 쓴 바이트 개수를 반환한다. 이 반환값은 반드시 count * iov_len 값과 같아야 한다. 에러가 발생하면 -1을 반환하고 errno를 적절한 값으로 설정한다.

예제

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/uio.h>

int main()
{
    struct iovec iov[3];
    ssize_t nr;
    int fd, i;

    char *buf[] = {
        "the one.\n",
        "the two2.\n",
        "the three3.\n",
    }

    fd = open("text.txt", O_WRONLY | O_CREAT | O_TRUNC);

    for (i = 0; i < 3; i++)
    {
        iov[i].iov_base = buf[i];
        iov[i].iov_len = strlen(buf[i]) + 1;
    }

    nr = writev(fd, iov, 3);
    if (nr == -1)
    {
        perror("writev");
        return 1;
    }
    printf("wrote %d bytes\n", nr);

    if (close(fd))
    {
        perror("close");
        return 1;
    }
    return 0;
}

    
    

0개의 댓글