2012-05-09 23 views
50

Trong phân tánthu thập (ví dụ: readvwritev), Linux đọc thành nhiều bộ đệm và viết từ nhiều bộ đệm.Linux: Khi sử dụng phân tán/thu thập IO (readv, writev) vs một bộ đệm lớn với fread

Nếu nói, tôi có vectơ 3 bộ đệm, tôi có thể sử dụng readv, HOẶC Tôi có thể sử dụng một bộ đệm đơn, có kích thước kết hợp là 3 bộ đệm và làm fread.

Do đó, tôi bị nhầm lẫn: Trường hợp nào nên phân tán/thu thập được sử dụng và khi nào một bộ đệm lớn sẽ được sử dụng?

Trả lời

83

Sự tiện lợi chính được cung cấp bởi readv, writev là:

  1. Nó cho phép làm việc với các khối không tiếp giáp của dữ liệu. tức là bộ đệm cần không phải là là một phần của mảng, nhưng được phân bổ riêng.
  2. I/O là 'nguyên tử'. tức là nếu bạn thực hiện writev, tất cả các phần tử trong vectơ sẽ được viết trong một thao tác liền kề và ghi được thực hiện bởi các quá trình khác sẽ không xảy ra ở giữa chúng.

ví dụ: tiếng nói, dữ liệu của bạn một cách tự nhiên phân đoạn, và xuất phát từ nhiều nguồn khác nhau:

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

Bây giờ, cả ba 'đệm' là không một khối liền kề lớn. Nhưng bạn muốn viết chúng liên tục vào một tệp, vì bất kỳ lý do nào (ví dụ: chúng là các trường trong tiêu đề tệp cho định dạng tệp).

Nếu bạn sử dụng write bạn phải lựa chọn giữa:

  1. sao chép chúng qua thành một khối bộ nhớ sử dụng, chẳng hạn, memcpy (overhead), tiếp theo là một write cuộc gọi duy nhất. Sau đó, viết sẽ là nguyên tử.
  2. Thực hiện ba cuộc gọi riêng biệt đến write (trên cao). Ngoài ra, write cuộc gọi từ các quá trình khác có thể xen kẽ giữa các lần ghi này (không phải nguyên tử).

Nếu bạn sử dụng writev thay vào đó, tất cả của nó tốt:

  1. Bạn thực hiện đúng một cuộc gọi hệ thống, và không có memcpy để thực hiện một bộ đệm duy nhất từ ​​ba.
  2. Ngoài ra, ba bộ đệm được viết bằng nguyên tử, như một khối viết. tức là nếu các quy trình khác cũng viết, thì những ghi chép này sẽ không đi vào giữa việc viết ba vectơ.

Vì vậy, bạn sẽ làm điều gì đó như:

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

Nguồn:

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

trong 'Linux Hệ thống Programming' cuốn sách, họ nói' readv hoặc writev có thể trải nghiệm bất kỳ lỗi của cuộc gọi hệ thống read() và write(), và sẽ, khi nhận được các lỗi như vậy, đặt cùng một mã errno.' Vì vậy, sẽ readv trả về 'EINTR'? Hoặc điều gì sẽ xảy ra với một tín hiệu xảy ra giữa sự đọc nguyên tử của readv? nó sẽ bị bỏ qua hoặc xếp hàng đợi. – nmxprime

+0

@nmxprime nếu tín hiệu đến trong 'readv()' hoặc 'writev()', các syscalls này (tùy thuộc vào SA_RESTART) sẽ trả lại ít byte hơn yêu cầu. – socketpair

+0

Tôi có thể viết bộ đệm không tiếp giáp trong tệp theo kiểu không tiếp giáp và không phải là toàn bộ khối không? – RAFA

Các vấn đề liên quan