回答:
@Kusalanandaが述べたように、通常、アップグレードは古いファイルを削除し、同じ名前で新しいファイルを作成することによって行われます。これにより、実際には新しいiノードで新しいファイルが作成され、システムが開いている限り、システムは古いファイルを自由に使用できます。
簡単な例として、次のようなもの
rm /bin/cat
cp /new/version/of/cat /bin/cat
論理的に新しいファイルを作成し、cat
実行中であっても機能します。ライブラリについても同様です。(上記は一例であり、実際のファイルを確実にアップグレードする方法ではありません。)
誰かが同じ名前で新しいバイナリを作成する代わりに、バイナリをインプレースで変更しようとする可能性があります。この場合、少なくともLinuxは、使用中の実行可能ファイルへの変更を実際に防止します。
window 1 # ./cat
window 2 # echo foobar > cat
-bash: cat: Text file busy
ただし、これは動的に読み込まれるライブラリでは機能しないようです...
libc.so.6
テスト用にコピーを作成し、使用中はゼロで埋めました。
window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ldd ./cat
linux-vdso.so.1 (0x00007ffcfaf30000)
libc.so.6 => /tmp/lib/libc.so.6 (0x00007f1145e67000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1146212000)
window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ./cat
foo
foo
Segmentation fault
(その間、別のウィンドウで、の後foo
、segfaultの前)
window 2 /tmp/lib# dd if=/dev/zero of=libc.so.6 bs=1024 count=2000
オンラインでコードを効果的に編集したので、プログラム自体はこれに対して何も実行できません。
(これはシステムに依存する可能性があります。DebianJessie 8.5、Linux 3.16.7-ckt25-2 + deb8u3でテストしました。特にIIRC Windowsシステムは、使用中のファイルが変更されるのを防ぐことに関してさらに積極的です。)
だから私は答えはおそらくアップグレードは問題を回避する方法で行われ、これはファイルシステムの内部によって助けられていると思います。しかし(Linuxでは)実際に動的ライブラリが破損するのを防ぐ方法はないようです。
install
ユーティリティは、一般的にこのようなもののために使用されています。rm
宛先ファイルを明示的に指定する必要はありません。さらに、既存のファイルの権限を保持し、バックアップを作成したり、新しいモードを設定したりできます。使用例:install /new/version/of/cat /bin/cat
rm
+は、cp
一例として意図されました。また、どちらのバージョンも利用できない短いウィンドウを避けて、名前を変更して新しいファイルをアトミックに配置することも賢明かもしれません。(GNU install
はそれを実行していないようですが、hmpfです。)
rm
いて削除されている場合()、まだ削除されていません。これはディスク上に存在し、開いているすべてのプロセスで引き続き読み取ることができます。ハードリンクカウントがゼロに達し、ファイルを開いた状態での歳差運動の数がゼロに達したときにのみ削除されます。
install
ユーティリティは特に安全ではありません!ターゲットファイルを原子的に置き換えるのではなく、上書きします。mv
(sourceとdestが同じディレクトリにあり、sourceは通常一時ファイルです)ファイルをインストールする唯一の安全な方法です。
strace
伝え、install
GNUのcoreutilsの中にコピーに、その場所に新しいものをターゲットファイルのリンクを解除して。これは、ファイルが部分的である短いウィンドウがあることを意味します。名前を変更しても、ファイルがアトミックに設定されません。
ファイルを開いたままリンクを解除すると、ファイルは「適切に削除」されません。それらが閉じられると、使用したディスク領域は再び「空き」と見なされます。これは、現在実行中のアプリケーションとその共有ライブラリにも当てはまります。
プログラムdlopen()
が共有ライブラリをオンデマンドでロードするために使用されていた場合、またはプログラムが辞書、テーマファイル、または突然消えた他のファイルなどのオンデマンドで他のファイルにアクセスしなければならない場合にのみ、失敗する可能性があります。
たとえばvim
、あるシェルセッションでインストールを削除しながらvim
別のシェルセッションで実行しても、「破損」したり、現在実行vim
中のセッションが終了したりすることはありません。ただし、たとえばスペルチェックのようvim
に、インストールでファイルを開く必要があるものは失敗し始めます。
ln -sf
ので、ライブラリの上にスワップするとき-f
、あなたはそれなしに新しいものとシンボリックリンクの既存の先には、これまでに「壊れた」されている「上書き」を許可しますがなかった場合とは異なり、(rm
続きますaln -s
)。したがって、コマンドの前に、library.soは古いバージョンを指していました。library.so.4 ...コマンドの後に、それは単に指さlibrary.so.5代わりに(または何でも) -今までになしていない有効なライブラリを指します。