実行中の実行可能ファイルまたは.soの上書き

実行中の実行可能ファイルまたは.soの上書き

実行中の実行可能ファイルの上書きまたは1つ以上の実行可能プログラムで使用されている共有ライブラリ(.so)ファイルの上書きに関する質問があります。

以前は、実行中の実行可能ファイルを上書きすることは明らかな理由で機能しませんでした。この状況に対処する特定のerrno値ETXTBSYもあります。

しかし、長い間、私は誤って実行中の実行可能ファイルを上書きしようとすると(たとえば、実行中のビルドの最後のステップを実行して)動作することがわかりましたcc -o exefileexefile

だから私の質問は、これがどのように機能するのか、どこに文書化されているのか、そしてそれに頼っても安全です。

ldこの場合、エラーを排除するために、誰かが出力ファイルのリンクを解除して新しいファイルを作成するように調整したようです。この作業を常に実行するのか、それとも必要なときに実行するのか(つまり、既存のファイルを上書きしようとし、ETXTBSYに遭遇した後)はわかりません。ldマニュアルページにはこれに関する言及はありません。 (誰がld今ハードリンクを破ったり、ファイルの所有権を変更したりする可能性などについて不平を言わないのだろうか?)


cc付録:この質問は/に関するものではありませんld(最終的には答えの重要な部分になりましたが)。質問は実際に「なぜこれ以上ETXTBSYを見ることができないのですか?これはまだバグですか?」です。はい、まだバグです。実際には珍しいバグです。 (私の質問に投稿した明確な答えも参照してください。)

ベストアンサー1

これはカーネルによって異なり、一部のカーネルでは実行可能ファイルの種類によって異なりますが、すべての最新システムはETXTBSY( "テキストファイルbusy") 書き込み用に実行中の実行可能ファイルを開こうとしているか、書き込み用に開いているファイルを実行しようとすると、ドキュメントに記載されています。BSDでは常にこのようなことがありました。、しかし初期のソラリスではそうではありませんでした。以降のバージョンでは、この保護機能を実装しました。)、私の記憶と一致します。 Linuxでは常にそうです。最小1.0

実行可能ファイルに適用されるものは、動的ライブラリに適用されても適用されなくてもよい。動的ライブラリを上書きすると、実行可能ファイルを上書きするのとまったく同じ問題が発生します。コマンドは、まったく異なる内容を含む可能性がある新しいファイルの同じ古いアドレスから突然ロードされます。しかし、実際にはどこでもそうではありません。特に、Linuxでは、プログラムはopenすべてのデータファイルと同じフラグを使用して内部的に動的ライブラリを開くためにシステムコールを呼び出します。Linuxでは、実行中のプロセスがいつコードをロードしてもライブラリファイルをオーバーライドできます。

ほとんどのカーネルでは、ファイルの開いたり書き込んだりしてファイルを削除したり名前を変更したりするのと同じように、実行中にファイルを削除して名前を変更できます。開いたファイルと同様に、実行中に削除されたファイルは使用中、つまり実行可能ファイルの最後のインスタンスが終了するまで実際には記憶媒体から削除されません。 Linuxおよび* BSDではこれを許可しますが、SolarisおよびHP-UXでは許可しません。

ファイルを削除し、同じ名前で新しいファイルを作成することは非常に安全です。ロードするコードとそのコードを含む開いている(または実行する)ファイルとの間の関連付けは、ファイル名ではなくファイル記述子を介して行われます。rename一時ファイルに書き込んだ後、そのファイルを所定の位置に移動する(既存のターゲットファイルをソースファイルにアトミックに置き換えるシステムコール)、これを自動的に実行できるという利点があります。無効または部分的に作成された実行可能ファイルを一時的に配置しないため、削除してから書き込み用に開くよりもはるかに優れています。

cc出力ファイルを上書きするか、削除して新しいファイルを作成するかは、実装ldによって異なります。 GCC(最小最新バージョン)とClangの両方がこれを行います。どちらの場合も、unlinkターゲット(存在する場合)を呼び出してopen新しいファイルを作成します。 (なぜ一時書き込み後に名前を変更しないのか疑問に思います。)

保護措置を除いて、この動作に依存しないことをお勧めします。なぜなら、この動作はすべてのシステムでは機能せず(おそらく実行可能ファイルについてはすべての最新のシステムで動作しますが、共有ライブラリでは動作しません)、一般的なツールチェーンでは動作しないからです。可能な限り最善の方法です。ビルドスクリプトは常に一時ファイルの下にファイルを生成し、デフォルトのツールがこれを行うかどうかわからない場合は、その場所に移動します。

おすすめ記事