2012-05-17 8 views
18

現在、splice/vmspliceの値を理解しようとしています。 https://stackoverflow.com/a/1350550/1305501Linuxゼロコピー:vmspliceで2つのプロセス間でメモリページを転送する

質問:データをコピーせずにvmspliceを使用して他のプロセスに一つのプロセスからメモリページを転送する方法(すなわち、ゼロコピー)IPCのユースケースについては、私はstackoverflowの上、以下の答えにつまずきましたか?

上記の回答は可能です。ただし、ソースコードは含まれていません。 vmspliceのドキュメントが正しく理解されていれば、メモリが適切に割り当てられて整列されていれば、次の関数はメモリページをコピーせずにパイプ(カーネルバッファ)に転送します。提示の容易さのためにエラー処理が省略されました。

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

しかし、どのようにメモリページをコピーせずにユーザスペースからアクセスできますか?どうやら以下の方法はうまくいかない:

  • vmsplice:この機能は逆方向にも使用できます。しかし、kernel sourcesのコメントによれば、データはコピーされます。
  • read私は、メモリが正しく整列されていれば、この機能はいくつかの魔法をしますが、私はそれを疑っています。
  • mmap:パイプでは不可能です。しかし、代わりに使用できる仮想ファイルがあります。すなわち、splice仮想ファイルのメモリページとmmapです。
  • ...?

vmspliceと全く同じですか?

+4

"send()"という名前の非静的関数を作成することはお勧めできません。 – wildplasser

+1

実際、これはPOSIXで未定義の動作を引き起こしています。 –

+0

私はあなたの 'vmsplice'への' receive'の呼び出しが意味をなさないと思います。これは、書き込むべきではなく、読み込まないようにするための呼び出しです... –

答えて

6

Rが述べたように、fdを受信プロセスsomehowに渡すだけで、反対側では通常のfdとして使用する必要があります。

編集: は実際に、あなたは、パイプのもう一方の端には、受信側の配管およびスプライス()にバッファをマップするために、送信側()vmspliceを使用する必要があります。例hereを参照してください。

もう1つの選択肢は、共有mmapingを使用することです。

+3

もう一方のプロセスにはすでにパイプのもう一方の端にfdがあるとします。問題は次のとおりです。データをコピーせずにメモリページをアドレス空間にマップできますか?私は 'read(2)'にそのような最適化が含まれているのではないかと疑っています。 – nosid

+0

カーネルはこのページのマッピングを処理する必要があります。また、私の編集を参照してください。 – dtatulea

関連する問題