2012-05-09 8 views
50

W rozpraszania i zbierać (tj readv i writev) Linux w różnych buforach odczytuje i zapisuje z wielu buforów.Linux: Kiedy użyciu rozproszenia/zebrania IO (readv, writev) w porównaniu do dużej buforze fread

Jeśli mówię, że mam wektor 3 buforów, mogę użyć readv, LUB mogę użyć pojedynczego bufora, który ma łączny rozmiar 3 buforów i zrobić fread.

W związku z tym jestem zdezorientowany: w jakich przypadkach należy stosować rozproszenie/zbieranie i kiedy należy użyć jednego dużego bufora?

Odpowiedz

83

Głównym wygoda oferowane przez readv, writev jest:

  1. Umożliwia pracę z nie sąsiadujących ze sobą bloków danych. tj. bufory potrzebują nie być częścią tablicy, ale są przydzielane osobno.
  2. We/wy jest "atomowa". Jeśli zrobisz writev, wszystkie elementy w wektorze będą zapisane w jednej ciągłej operacji, a zapisy wykonane przez inne procesy nie pojawią się między nimi.

np. powiedzmy, dane są naturalnie na segmenty, a pochodzi z różnych źródeł:

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(); 

Teraz wszystkie trzy „zderzaki” są nie jeden wielki blok sąsiaduje. Ale chcesz zapisać je w sposób ciągły do ​​pliku, z dowolnego powodu (powiedzmy na przykład, że są to pola w nagłówku pliku dla formatu pliku).

Jeśli używasz write trzeba wybierać pomiędzy:

  1. Kopiowanie je w jednym bloku pamięci za pomocą powiedzmy memcpy (overhead), a następnie jednym write rozmowy. Wtedy zapis będzie atomowy.
  2. Wykonywanie trzech oddzielnych połączeń z numerem write (narzut). Również wywołania z innych procesów mogą przeplatać się między tymi zapisami (nie atomowymi).

Jeśli używasz writev zamiast jego dobre: ​​

  1. dokonać dokładnie jedno wywołanie systemowe, a nie memcpy aby pojedynczy bufor z trzech.
  2. Również trzy bufory są zapisywane atomowo, tak jak pisze jeden blok. to znaczy, jeśli inne procesy również zapisują, to te zapisy nie pojawią się pomiędzy zapisami trzech wektorów.

Więc zrobiłbyś coś takiego:

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); 

Źródła:

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

W 'System Linux Programming' książki, mówią' readv lub writev może napotkać dowolny z błędy wywołań systemowych read() i write() i po otrzymaniu takich błędów, ustawiają te same kody errno. "Czyli readv zwróci' EINTR'? Albo co stanie się z sygnałem, który zachodzi pomiędzy odczytami atomowymi readv? zostanie zignorowany lub stanie w kolejce. – nmxprime

+0

@ nmxprime jeśli sygnał nadszedł podczas 'readv()' lub 'writev()', te syscalls (w zależności od SA_RESTART) zwrócą mniej bajtów niż żądano. – socketpair

+0

Czy mogę zapisać nieprzyległy bufor w pliku w sposób nieciągły, a nie jako cały blok? – RAFA

Powiązane problemy