web-dev-qa-db-ja.com

process_vm_readvを使用して任意の量のメモリを読み取ります

Process_vm_readvの場合、Linuxのマニュアルページには次のように記載されています。

[...](回避)単一のリモートiovec要素でメモリページ(通常は4KiB)にまたがる。 (代わりに、リモート読み取りを2つのremote_iov要素に分割し、それらを1つの書き込みlocal_iovエントリにマージして戻します。最初の読み取りエントリはページ境界まで上がり、2番目は次のページ境界から始まります。)

なぜこれが問題なのかはわかりますが、どうすれば回避できるのかよくわかりません。どういうわけか、ページの境界がどこにあるかを見つける必要がありますか?または、2つのremote_iov要素を提供する限り、関数はそれ自体でこれを理解しますか?また、4kiBを超えて読み取り、2ページの境界を超える可能性がある場合、リモート要素を3つの部分に分割する必要がありますか?

1
HenrikS

あなたは本当に段落全体を読むべきです-iovecsを分割するその方法は難しい要件ではありません。部分的な読み取りの場合に役立つのはsupposedだけですが、どのように役立つかは明確ではありません;-)

そのマンページは非常に疑わしく、混乱を招きます。私のテストでは、_iov_start_リストの最初のiovecの_remote_iov_が有効なアドレスでない場合、process_vm_readv()は常にエラーになりますが、いずれかのページがあれば部分読み取りを返します。 _iov_start + iov_len_にまたがる、または残りのiovecはマップされません(これは期待されて有用ですが、以下の強調された部分と矛盾します)。

ただし、これらのシステムコールは、リモートプロセスのメモリ領域をチェックしないことに注意してください読み取り/書き込みを実行する直前まで。したがって、_remote_iov_要素の1つがリモートプロセスの無効なメモリ領域を指している場合、部分的な読み取り/書き込み(戻り値を参照)が発生する可能性があります。その時点を超えて、それ以上の読み取り/書き込みは試行されません。単一のリモートiovec要素でメモリページ(通常は4KiB)にまたがらないようにして、リモートプロセスから長さが不明なデータ(nullで終了するC文字列など)を読み取ろうとする場合は、このことに注意してください。 (代わりに、リモート読み取りを2つの_remote_iov_要素に分割し、それらを1つの書き込み_local_iov_エントリにマージします。最初の読み取りエントリはページ境界まで上がり、2番目のエントリは次のページから始まります。境界。)

[...]

部分的な読み取り/書き込みが発生した場合、この戻り値は要求されたバイトの総数よりも少なくなる可能性があります。 (部分転送iovec要素の粒度で適用します。これらのシステムコールは、単一のiovec要素を分割する部分転送を実行しません。)

0
mosvy