PROT_NONEをmprotect
持つセグメントであり、SIGSEGV
によって処理される書き込みが原因で発生したsigaction
場合、sa_sigaction
を使用して障害が発生したアドレスを見つけることができsiginfo_t
ますsi_addr
。しかし、書き込まれようとしたデータとデータの長さを見つける方法はありますか?
プロジェクトでコピーオンライトメカニズムを試しているため、これを実行しようとしています。
PROT_NONEをmprotect
持つセグメントであり、SIGSEGV
によって処理される書き込みが原因で発生したsigaction
場合、sa_sigaction
を使用して障害が発生したアドレスを見つけることができsiginfo_t
ますsi_addr
。しかし、書き込まれようとしたデータとデータの長さを見つける方法はありますか?
プロジェクトでコピーオンライトメカニズムを試しているため、これを実行しようとしています。
プロセスが書き込もうとしたデータが見つからないか、そのサイズを尋ねる意味がありません。データを取得できた場合は、カーネルがすでにデータをどこかにコピーしたことを意味します。
SIGSEGV
ページ全体で を取得します。つまり、プロセスが書き込んでいるデータに関係なく、最初にバイトを書き込もうとしたときに、ページごとに 1 つのエラーが発生します。したがって、必要なことは次のとおりです。
カーネルは知らないので、あなたに教えることはできません。しかし、必要に応じて調べることができます。スタックでエラーが発生したコード アドレスがあるので、そこでコードを逆アセンブルして、それを把握することができます。他に知る方法はありません (理由が明らかでない場合は、考えてみてください)。命令が保護されたページに触れたためにエラーが発生しました。これは、アセンブリ コードを分析しない限りわかりません。
エラーが発生したページだけを知っていても、どのオブジェクトを扱っているかがわからない場合は、そうするようにデザインを変更することを再検討することを強くお勧めします。(posix_memalign
、もしかして?)
更新: すべてのコンテキスト スイッチで呼び出されるフックが必要であることを忘れないでください。各フックでページをコピーする必要がある場合があります。例えば:
コンテキスト A は、CoW セマンティクスを使用してページ Q にアクセスしています。コンテキスト A は、ページへの読み取り専用アクセスを取得します。
コンテキスト B は、CoW セマンティクスを使用してページ Q にアクセスしています。コンテキスト B は、ページへの読み取り専用アクセスを取得します。
コンテキスト A がページを変更し、コンテキスト B のコピーを作成します。コンテキスト A はページへの書き込みアクセス権を持ち、ページを変更します。
コンテキスト A からコンテキスト B に切り替えます。この時点で、コンテキスト B 用に作成したページのコピーに切り替える必要があります。
これを回避するもう 1 つの方法は、コンテキストにページのマップとロックへの特定の呼び出しを行わせることです。コンテキストがコンテキストスイッチ全体でマッピングを保持できるようにすると、これは機能しません。少なくとも、多くの追加作業がなければ機能しません。