7

SQLite3を使用してデータベースファイルを維持するコンソールモードプログラムがあります。実行にはしばらく時間がかかりますが、データベースへの書き込みが発生したと仮定すると、いつでもキャンセルしても安全です。(これはすべてWindowsの下にあります)

CtrlC実行中のプログラムの観点から、別のプログラムがTerminateProcessを呼び出すよりも、コンソールでヒットする方が安全ですか?

TerminateProcessが呼び出されると、データベースが破損する可能性があることに気付きました。これは、プログラムが書き込みを終了する機会がないためだと思います。私の推測ではCtrlC、OSがシグナルを強制終了するのではなく、プログラムがシグナルを取得してそれ自体を終了するため、それが優れていると思います。

プログラムは実際にはシグナルを処理しないことに注意してください(SQLiteが処理しない限り)。シグナルを処理するためのWin32実行可能ファイルの組み込みのデフォルトメカニズムについて話していますCtrlC

質問を明確化/単純化するには-この書き込みが実行されたばかりであるとすると、次のようになります。

fwrite(buf, 1024*1024, 1, stream);

この書き込み中、TerminateProcessの動作は?とは異なりCtrlCますか?

4

4 に答える 4

6

これらはすべて説得力のある議論ですが、確実に知る唯一の方法はそれを試すことです。そこで、1GBのバッファを割り当て、それにデータを割り当て、単一のfwrite()を使用してファイルに書き込む簡単なプログラムを作成しました。データを「破損」させるための書き込みを取得するために、いくつかの方法を試しました(具体的には、切り捨てられたファイルを期待していました)。

  • TerminateProcessの呼び出し(perlのkill関数とWin32 :: Process :: Killを介して)
  • ヒッティングCtrlC
  • タスクマネージャの「エンドプロセス」を使用する
  • ProcessExplorerの「Kill​​Process」を使用する

書き込みを停止するものは何もありません。どの場合でも、ファイルは正しいサイズであり、正しいデータを持っていました。そして、「キル」は即座に発生しますが、書き込みが完了するまでプロセスは長続きします。

TerminateProcessとI/Oの観点からは、違いはないと結論付けられているようですCtrlC。書き込みが開始されると、(停電を除いて)完了することが保証されているようです。

于 2009-08-04T22:02:45.497 に答える
1

SQLiteは、停電中でもアトミックであると主張しています。http: //www.sqlite.org/atomiccommit.htmlを参照してください。

これに対する唯一の例外は、一部のディスクシステムは、データが実際にディスクプラッタに書き込まれる前に、つまりデータがディスクキャッシュにあるか、オペレーティングシステムがSQLiteに依存している前に、書き込みが正常に行われたことを報告することです。http://www.sqlite.org/lockingv3.htmlセクション6.0データベースファイルを破損する方法を参照してください。

終了したプロセスは、実行中のすべてのスレッドを停止し、終了する前に保留中のI/O操作を完了する必要があります。プロセスがクラッシュしていない限り、データの整合性を保証する必要があります。

于 2009-07-25T15:56:33.930 に答える
1

アプリケーションは処理する機会がCtrlCありCtrlBreak、キーストロークまたはシグナル(構成によって異なります)として、アプリケーションがクリーンな終了を行う機会があることを意味します。これは、プロセスを終了するためのはるかにソフトな方法であり、少し許可します。他に何もないとしても、実行時間は長くなります。

TerminateProcessは歯のキックのようなものであり、アプリケーションはこれを処理できません。これはカーネルからのものであり、アプリケーションがそれを処理できる場合、これにより、TerminateProcessハンドラーがハングし、出口。

私が理解しているように、TerminateProcessがプロセスで呼び出されるとすぐに、それ以上のコードを実行できなくなり、クリーンアップもシャットダウンも実行できなくなります。処理できなくなります。できれば意味がありません。セキュリティの観点からではありません。

Windowsコンソール信号の処理に関する優れたコードプロジェクトの記事:

http://www.codeproject.com/KB/winsdk/console_event_handling.aspx

上記の信号処理の一部を実装すると、プログラムが終了する前にデータベースへの書き込みが完了する可能性があり、プログラムが偶然に任せられる可能性はありません。

TerminateProcessをブロックすることはできますが、その「丁寧な」プログラミングではなく、ルートキットプログラミングに似ています。rootkit.comでこれに関する優れた記事を見たので、無敵のプロセスができたら、そこで「ProcessInvincibility」を検索してください。このような「リクエスト」を受け取った後、それ自体でシャットダウンし、hnadの前にクリーンアップを実行することもできますが、これは間違いなくハックです。

CtrlC現在表示されている動作は、実行中のプロセスがすぐに終了しないためであるように思われます。

于 2009-07-27T12:27:33.660 に答える
0

私はあなたの目的のために、使用する方が安全だと信じていますCtrlC。これにより、プログラムに送信されたシグナルが終了します。プログラムが信号を処理しない場合、その場で終了します。

TerminateProcessは、プロセスとすべての子スレッドを強制的に終了します。

MSDNから:

TerminateProcess関数指定されたプロセスとそのすべてのスレッドを終了します。... 備考

TerminateProcess関数は、プロセスを無条件に終了させるために使用されます。ExitProcessではなくTerminateProcessを使用すると、ダイナミックリンクライブラリ(DLL)によって維持されるグローバルデータの状態が損なわれる可能性があります。

TerminateProcessは終了を開始し、すぐに戻ります。これにより、プロセス内のすべてのスレッドの実行が停止し、保留中のすべてのI/Oのキャンセルが要求されます。終了したプロセスは、保留中のすべてのI/Oが完了するかキャンセルされるまで終了できません。

プロセスは、それ自体が終了するのを防ぐことはできません。

プロセスがTerminateProcessをブロックする方法はいくつかありますが、SQLite3がそれをブロックするかどうかは疑問です。

于 2009-07-27T21:04:39.297 に答える