Sự tiện lợi chính được cung cấp bởi readv
, writev
là:
- 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.
- 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:
- 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ử.
- 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:
- 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.
- 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:
- http://pubs.opengroup.org/onlinepubs/009604499/functions/writev.html
- http://linux.die.net/man/2/readv
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
@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
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