21

Win32にCreateFileは がありますFILE_FLAG_DELETE_ON_CLOSEが、私は Linux を使用しています。

プログラムの終了時に常に削除される一時ファイルを開きたいです。プログラムがクラッシュした場合、これを保証するのは現実的ではないかもしれないことは理解できましたが、それ以外の場合は動作させたいと思っています。

私はRAIについて知っています。信号については知っています。について知っていatexit(3)ます。ファイルを開いてすぐに削除できることはわかっていますが、ファイル記述子が閉じられるまで (クラッシュを処理することさえあります)、ファイルは引き続きアクセス可能です。これらのどれも完全で簡単な解決策のようには見えません:

  1. RAII: 行ったこと: デストラクタがファイルを削除するオブジェクトがありますが、プログラムがシグナルによって終了された場合、デストラクタは呼び出されません。
  2. シグナル: シグナル ハンドラーの登録をトリッキーな命題にする低レベルのライブラリを作成しています。たとえば、アプリケーションがシグナル自体を使用する場合はどうなるでしょうか。つま先を踏みたくない。対処するために を巧妙に使用することを検討するかもしれませんsigaction(2)が、この可能性についてはまだ十分に考えていません。
  3. atexit(3): 異常終了時に呼び出されないため (たとえば、シグナルを介して)、明らかに役に立たない。
  4. preemptive unlink(2): ファイルをファイル システムに表示したままにしておく必要があることを除けば、これは非常に優れています (そうしないと、システムの監視やトラブルシューティングが難しくなります)。

ここで何をしますか?

詳細説明

元の投稿で 1 つの詳細を省略しましたが、含める必要があったことに今気づきました。この場合の「ファイル」は、厳密には通常のファイルではなく、POSIX メッセージ キューです。経由で作成しmq_open()ます。mq_close()orで閉じることができますclose()(前者は私のシステムでは後者のエイリアスです)。経由でシステムから削除できますmq_unlink()。ファイルが存在するディレクトリを選択できないことを除いて、これらすべてが通常のファイルに似ています。/tmp「ファイル」は非常に限られた容量の仮想ファイルシステムでシステムによって作成されるため、これにより、現在最も一般的な回答 (ファイルを に配置する) が機能しなくなります。/dev/mqueue(の例に従って、仮想ファイルシステムを にマウントしましたman mq_overview) 。

これは、名前を表示したままにしておく必要がある理由も説明しています (即時リンク解除アプローチが機能しなくなります)。「ファイル」は 2 つ以上のプロセス間で共有する必要があります。

4

8 に答える 8

7

プロセスの実行中に名前を表示したままにしておく必要があるため、これを達成するのは困難です。その要件を再検討できますか?

そうでない場合、おそらく完璧な解決策はありません。シグナル処理戦略とカミル・キシエルの提案を組み合わせることを検討します。シグナル ハンドラーをインストールする前に、インストールされているシグナル ハンドラーを追跡できます。デフォルトのハンドラーが SIG_IGN の場合、通常は独自のハンドラーをインストールしません。SIG_DFL の場合は、それを覚えているでしょう。それが何か他のもの (ユーザー定義のシグナル ハンドラー) である場合は、そのポインターを覚えておいて、独自のものをインストールします。ハンドラーが呼び出されたら、必要なことをすべて実行してから、記憶したハンドラーを呼び出して、ハンドラーをチェーンします。atexit() ハンドラもインストールします。また、これを行うことと、それを行うシグナルを文書化します。

シグナル処理は不完全な戦略であることに注意してください。SIGKILL はキャッチできず、atexit() ハンドラーは呼び出されず、ファイルはそのまま残ります。

David Segond の提案 - 一時ファイル名デーモン - は興味深いものです。単純なプロセスの場合は、これで十分です。一時ファイルを要求するプロセスが fork し、その後子がファイルを所有することを期待する (そして終了する) 場合、デーモンは、それを使用している最後のプロセスがいつ終了したかを検出する際に問題があります。

于 2009-01-23T02:52:42.793 に答える
6

一時ファイルを作成するだけの場合は、/tmpまたはそのサブディレクトリに作成します。atexit(3)その後、または同様の作業を行ったときに、それを取り除くために最善の努力をしてください。mkstemp(3)プログラムのクラッシュのために削除に失敗した場合でも、取得した一意の名前または類似の名前を使用している限り、その後の実行またはその他のそのような状況で再度読み取るリスクはありません。

その時点では、/tmpクリーンな状態を保つというシステム レベルの問題にすぎません。ほとんどのディストリビューションは、起動時またはシャットダウン時に消去するか、通常の cron ジョブを実行して古いファイルを削除します。

于 2009-01-23T00:00:41.690 に答える
4

誰かがすでにこれを提案しているかもしれませんが、あなたのすべての要件を考えると、私はそれを見つけることができません。失敗した場合、プロセスは終了します。これはおそらく主にウォッチドッグとして知られていますが、何らかの理由でプロセスが失敗したときにプロセスを強制終了および/または再起動するためのより一般的なユースケースが追加されています。

親プロセスも停止した場合は、ほとんど運がありませんが、ほとんどのスクリプト環境はかなり堅牢であり、スクリプトが壊れていない限り停止することはめったにありません。これは、多くの場合、プログラムよりも正しい状態を維持する方が簡単です。

于 2009-01-23T14:21:01.033 に答える
3

過去に、一時ファイルを追跡する「一時ファイルマネージャー」を作成しました。

管理者に一時ファイル名を要求すると、この名前が登録されました。

一時ファイル名が不要になったら、管理者に通知し、ファイル名を登録解除します。

終了信号を受信すると、登録されているすべての一時ファイルが破棄されました。

衝突を避けるために、一時的なファイル名は UUID ベースでした。

于 2009-01-23T00:02:42.763 に答える
1

ファイルの作成後にプロセスを分岐させ、子が閉じるのを待ってから、親がファイルのリンクを解除して終了することができます。

于 2009-01-23T14:19:19.337 に答える
1

私はスタックオーバーフローに参加したばかりで、ここであなたを見つけました:)

問題が mq ファイルを管理し、それらが山積みにならないようにすることである場合、終了時にファイルの削除を保証する必要はありません。役に立たないファイルが山積みになるのを防ぎたいだけなら、日記をつけるだけで十分かもしれません。mq が開かれた後にジャーナル ファイルにエントリを追加し、閉じられたときに別のエントリを追加し、ライブラリが初期化されたときに、ジャーナルの不整合をチェックし、不整合を修正するために必要なアクションを実行します。が呼び出されたときにクラッシュすることが心配な場合mq_open/mq_closeは、これらの関数が呼び出される直前にジャーナル エントリを追加することもできます。

于 2009-04-28T16:45:23.107 に答える
1

名前を表示したままにしておく必要があります?

ファイルのリンクをすぐに解除するオプションを選択したとします。それで:

  • preemptive unlink(2): ファイルをファイル システムに表示したままにしておく必要があることを除けば、これは非常に優れています (そうしないと、システムの監視やトラブルシューティングが難しくなります)。

    削除されたファイルは の下にまだ表示されているため、引き続きデバッグできます/proc/$pid/fd/。プロセスの pid を知っている限り、開いているファイルを列挙するのは簡単です。

  • 名前はプログラム間で共有されるため、通常の操作中に表示されたままにする必要があります。

    Unix ドメインソケットを介してファイル記述子を渡すことにより、削除された開いているファイルをプロセス間で引き続き共有できます。詳細については、異なるプロセス間でファイル記述子を渡すポータブルな方法を参照してください。

于 2012-08-14T00:35:40.837 に答える