Program Club

Linux : 분산 / 수집 IO (readv, writev)와 fread가있는 대용량 버퍼를 사용하는 경우

proclub 2020. 12. 12. 11:39
반응형

Linux : 분산 / 수집 IO (readv, writev)와 fread가있는 대용량 버퍼를 사용하는 경우


에서 분산수집 (즉, readvwritev), 리눅스는 다중 버퍼와 여러 버퍼에서 쓰기로 읽습니다.

만약 내가 3 개의 버퍼로 구성된 벡터를 가지고 있다면,를 사용할 수 있습니다 readv. 또는 3 개의 버퍼를 결합한 단일 버퍼를 사용할 수 있습니다 fread.

따라서 혼란 스럽습니다. 어떤 경우에 분산 / 수집을 사용해야하며 단일 대형 버퍼를 언제 사용해야합니까?


가 제공하는 주요 편의 readv, writev이다 :

  1. 연속되지 않은 데이터 블록으로 작업 할 수 있습니다. 즉, 버퍼가 필요 하지 배열의 일부 있지만, 별도로 할당합니다.
  2. I / O는 '원자 적'입니다. 즉,를 수행 writev하면 벡터의 모든 요소가 하나의 연속 작업으로 작성되고 다른 프로세스에서 수행 된 쓰기가 그 사이에 발생하지 않습니다.

예를 들어 데이터가 자연스럽게 세분화되고 다른 소스에서 가져 온다고 가정합니다.

struct foo *my_foo;
struct bar *my_bar;
struct baz *my_baz;

my_foo = get_my_foo();
my_bar = get_my_bar();
my_baz = get_my_baz();

이제 세 개의 '버퍼'모두 하나의 큰 연속 블록 아닙니다 . 그러나 어떤 이유로 든 파일에 연속적으로 기록하려고합니다 (예 : 파일 형식에 대한 파일 헤더의 필드).

사용하는 경우 다음 write중에서 선택해야합니다.

  1. memcpy(오버 헤드)를 사용하여 하나의 메모리 블록에 복사 한 다음 단일 write호출을 수행합니다. 그러면 쓰기는 원자적일 것입니다.
  2. write(오버 헤드)에 세 번의 개별 호출을 합니다. 또한 write다른 프로세스의 호출은 이러한 쓰기 사이에 분산 될 수 있습니다 (원 자성이 아님).

writev대신 사용하면 모두 좋습니다.

  1. 정확히 하나의 시스템 호출 memcpy을 만들고 세 개에서 단일 버퍼를 만들지 않습니다 .
  2. 또한 세 개의 버퍼는 하나의 블록 쓰기로 원자 적으로 기록됩니다. 즉, 다른 프로세스도 작성하는 경우 이러한 쓰기는 세 벡터의 쓰기 사이에 들어오지 않습니다.

따라서 다음과 같이 할 수 있습니다.

struct iovec iov[3];

iov[0].iov_base = my_foo;
iov[0].iov_len = sizeof (struct foo);
iov[1].iov_base = my_bar;
iov[1].iov_len = sizeof (struct bar);
iov[2].iov_base = my_baz;
iov[2].iov_len = sizeof (struct baz);

bytes_written = writev (fd, iov, 3);

출처 :

  1. http://pubs.opengroup.org/onlinepubs/009604499/functions/writev.html
  2. http://linux.die.net/man/2/readv

참고 URL : https://stackoverflow.com/questions/10520182/linux-when-to-use-scatter-gather-io-readv-writev-vs-a-large-buffer-with-frea

반응형