5

最近、私は c で書かれた約 3 ~ 4,000 行のコードを持つソフトウェアに取り組んでいました。セグメンテーション違反が発生し始めたとき、SIGSEGV ハンドラーを追加しました。バックトレースを与える。

私の質問は、SIGSEGV とは別に、エラー検出が容易になるように、大きなソフトウェアがある場合に処理すべき重要なシグナルは何かということです。

これは、オプションで攻撃を防ぐために使用できます。例 重要な更新/操作を行っているときにアボート信号を受信するソフトウェア。標準では、SIGHUP、SIGINT、SIGKILL、SIGPIPE、SIGTERM およびその他のいくつかの信号には、この信号が配信されたプロセスを終了するデフォルトのプロパティがあることが示されています。

したがって、ソフトウェアに別の保護層を追加するには、これらの信号の動作を変更する必要があります。保護とは、重要な更新の間にソフトウェアが終了しないようにすることを意味します。いつ終了するかを決定しますアボート。

編集:ソフトウェアがどのようにうまく設計されているか、シグナルを処理し、ソフトウェアが構築されているときに役立つセーフティネットのように使用することを知りたいです。

4

1 に答える 1

8

回答に何を期待するかは 100% 明確ではありませんが、一般的な考え方を説明しようと思います。

まず第一に、「デバッグ」シグナルと呼べるものは次のとおりです (およびそれらがいつ期待されるか):

  1. SIGILLSIGFPE— プログラムが不正な命令を実行しようとすると、通常、間違ったCFLAGSアセンブリや独自のアセンブリ (または深刻なランダム破損) が表示される可能性があります。
  2. SIGABRT— 呼び出しが原因abort()で、たとえばassert(). ライブラリから取得することもできるため、通常は処理する必要があります。
  3. SIGSEGV— 無効なメモリ アクセス。おそらく、すでにすべてのことを知っているでしょう。
  4. SIGBUSmmap()— I/O を実行し、アクセスできないメモリを読み書きしようとすると発生する可能性があります。mmap()また、ベースの I/O がスペースを使い果たしたときにも起こりました。
  5. SIGPIPE— パイプで I/O を実行しているときに、パイプが反対側から切断された場合。
  6. POSIXSIGSYSは無効なシステム コールも指定しており、おそらくそれもキャッチしたいと思うでしょう (ただし、私はそれを確認できませんでした)。

関連する操作を使用している場合は、これらのシグナルを処理する必要があると思います。#ifdefそれらはすべてPOSIXにありますが、すべてのシステムがそれらを実装しているかどうかはわかりませSIG*#ifdef

プログラムの実行中に遭遇する可能性のあるその他のシグナルは次のとおりです。

  1. SIGALRM— を使用する場合alarm()
  2. SIGPOLL— ポーリングを使用する場合、
  3. SIGCHLD— プロセスを生成するとき…</li>

そして、これらは基本的に、関連する操作を使用するときにとにかく処理しているシグナルであり、デフォルトで終了しますが、とにかくそれらのための他のハンドラーが必要です。

そして最後に、 userによって送信されたシグナルを処理することを期待する場合、それは厳しいケースです — ユーザーは事実上すべてのシグナルを送信できるからです。man signalしたがって、すべてを適切に処理したい場合は、デフォルトで終了アクションまたは中止アクションになるすべてのシグナルをキャッチする必要があります。

期待できるシグナルの一般的なサブセットをキャッチしたい場合は、次のようになります。

  1. SIGHUPプログラムを持つ端末 (または関連する場合は他の親) が死亡したとき、
  2. SIGINT^c キーの場合、
  3. SIGQUIT^\ キーの場合、
  4. SIGTERM終了要求(killデフォルトでプログラムおよび他の同様のツールによって送信される)の場合、
  5. SIGUSR1およびSIGUSR2ユーザー定義のシグナルであり、通常はプログラム固有のアクションを実行するために使用されます。それらはユーザーによって送信され、何らかの理由でデフォルトでプログラムを強制終了します。

もありますSIGKILLが、標準ではキャッチできません。

最も重要な信号をカバーできたことを願っています。私は Linux ユーザーであり、他の *nix にもキャッチしたい特定のシグナルがいくつかあることに注意してください。

それは通常、あなたが何を達成したいかによって異なります。ソフトウェアがランダムなシグナルによって中断されるのを防ぐことは良い考えですが、それらすべて、特にユーザーによって直接送信されるものによって強制終了されるのを防ぐことは通常価値がありません。

ユーザーがアプリを強制終了したい場合は、とにかくそれを達成できます。一般的なものを処理するだけで十分なはずSIGINTです —そしてSIGTERM. SIGQUIT私は個人的に(^\ キー) が重要なタスクさえも終了させずにアプリケーションを強制終了することを期待しています (SIGKILLそうです)。

編集します。最後の文の論理的根拠として、次のことを考えてみてください: 重要なデータを削除したなど、ばかげたことをしただけです。または、終了時のクリーンアップ手順に何か問題があることに気付いただけです。シグナルがキャッチされないようにプログラムを終了したいのですが、すぐに戻ります。たとえそれが壊れたデータになるとしても、データがないよりも壊れたデータを持っていることを本当に好むことがあります (必要なものを回復できることを願っています)

于 2012-07-23T20:39:43.153 に答える