2012-05-17 28 views
18

Hiện tại, tôi đang cố gắng hiểu giá trị của mối nối/vmsplice. Về trường hợp sử dụng của IPC, tôi stumbled khi câu trả lời sau đây trên stackoverflow: https://stackoverflow.com/a/1350550/1305501Linux Zero-Copy: Chuyển các trang bộ nhớ giữa hai quy trình với vmsplice

Câu hỏi: Làm thế nào để chuyển các trang bộ nhớ từ một quá trình quá trình khác sử dụng vmsplice mà không sao chép dữ liệu (ví dụ: zero-copy)?

Câu trả lời được đề cập ở trên cho rằng điều đó là có thể. Tuy nhiên, nó không chứa bất kỳ mã nguồn nào. Nếu tôi hiểu tài liệu của vmsplice chính xác, chức năng sau sẽ chuyển các trang bộ nhớ vào một đường ống (bộ đệm hạt nhân) mà không cần sao chép, nếu bộ nhớ được cấp phát và căn chỉnh đúng cách. Lỗi xử lý bị bỏ qua để dễ dàng trình bày.

// data is aligned to page boundaries, 
// and length is a multiple of the page size 
void transfer_to_pipe(int pipe_out, char* data, size_t length) 
{ 
    size_t offset = 0; 
    while (offset < length) { 
     struct iovec iov { data + offset, length - offset }; 
     offset += vmsplice(pipe_out, &iov, 1, SPLICE_F_GIFT); 
    } 
} 

Nhưng làm cách nào để các trang bộ nhớ được truy cập từ không gian người dùng mà không cần sao chép? Rõ ràng các phương pháp sau đây không hoạt động:

  • vmsplice: Chức năng này cũng có thể được sử dụng theo hướng ngược lại. Nhưng theo nhận xét trong số kernel sources, dữ liệu sẽ được sao chép.
  • read: Tôi có thể tưởng tượng, rằng chức năng này thực hiện một số phép thuật nếu bộ nhớ được căn chỉnh đúng cách, nhưng tôi nghi ngờ điều đó.
  • mmap: Không thể trên đường ống. Nhưng có một số loại tệp ảo có thể được sử dụng thay thế, tức là splice các trang bộ nhớ cho tệp ảo và mmap không?
  • ...?

Hoàn toàn không thể với vmsplice?

+4

Tôi không nghĩ rằng nên tạo một hàm không tĩnh có tên là "send()". – wildplasser

+1

Thật vậy, đó là gọi hành vi không xác định trên POSIX. –

+0

Tôi không nghĩ rằng lệnh gọi 'vmsplice' của bạn trong' receive' có ý nghĩa. Đó là một cuộc gọi để viết, không phải để đọc ... –

Trả lời

6

Như đã đề cập, bạn chỉ cần chuyển fd cho quy trình nhận somehow và ở phía bên kia sử dụng nó làm fd bình thường.

chỉnh sửa: Thực ra, bạn phải sử dụng vmsplice() ở phía gửi để ánh xạ bộ đệm vào đường ống và mối nối() trên mặt nhận ở đầu kia của đường ống. Xem ví dụ here.

Một lựa chọn khác là sử dụng tệp mmap được chia sẻ.

+3

Giả sử rằng quy trình khác đã có fd ở đầu kia của đường ống. Câu hỏi đặt ra là: Liệu nó có thể ánh xạ các trang bộ nhớ vào không gian địa chỉ của nó mà không cần sao chép dữ liệu? Tôi nghi ngờ rằng 'đọc (2)' chứa một tối ưu hóa như vậy, phải không? – nosid

+0

Nhân phải xử lý ánh xạ trang này. Ngoài ra, hãy xem chỉnh sửa của tôi. – dtatulea

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