たとえば、オンラインでシステムをアップグレードできるようにArch Linuxを使用しています。プログラム自体を使用している場合は、ブラウザパッケージをどのようにアップグレードしますか?それとも、例えばカーネル?新しい実行可能ファイルと置き換える前に実行可能ファイルを停止する必要がありますか?それとも、次回の再起動時にこれが発生しますか?
答え1
ディスク上のブラウザファイルが交換されたばかりです。実行中のプログラム(すべてがメモリにない場合)は、プログラムが閉じられるまで以前の実行可能ファイルを開いたままにします(ただし、そのファイルがディレクトリエントリから取得された実行可能ファイルではないまで)。次にブラウザを再起動すると、そのバージョンが表示されます。
再起動時にロードされるプログラム(カーネルなど)を除いて、再起動は不要です。カーネルを適切にパッチすることができ、再起動も不要なプログラムがありますが、同じではありません。
答え2
予想されるように、Unixシリーズシステムはほとんどの実行可能ファイルを上書きするのを防ぎます。以下は標準の関連内容です。開いているシステムコール:
次の場合、open()関数が失敗する可能性があります。
[ETXTBSY]このファイルは、oflag O_WRONLYまたはO_RDWRを使用して実行されている純粋なプロシージャ(共有テキスト)ファイルです。
しかし、実行中のファイルはまだ接続解除、これがパッケージマネージャの仕組みです。
Debian と Ubuntu にリリースされたばかりの新しいバージョンをインストールするdpkg
ときに実行する作業は次のとおりです。/bin/cpio
open("/bin/cpio.dpkg-new", O_WRONLY|O_CREAT|O_EXCL, 0) = 10
// lots of reads and writes omitted from this listing.
// It's copying the new version into dpkg-new
fchown(10, 0, 0) = 0
fchmod(10, 0755) = 0
close(10) = 0
rename("/bin/cpio.dpkg-new", "/bin/cpio") = 0
詳しく見ると次のようになります。
- 新しいバージョンを
cpio.dpkg-new
同じディレクトリにコピーしますcpio
。 - パッケージの指示に従って所有者とファイルの権限を設定します。
cpio.dpkg-new
次に名前を変更するcpio
ファイルが存在しない場所に存在せず(しばらくの間)、新しいバージョンのファイルを安全にインストールする方法は、次の方法を使用することです。名前を変更するシステムコール。これを行うには、両方のファイルが同じファイルシステムに存在する必要があり、これがdpkgが古いバージョンと同じディレクトリに新しいバージョンのcpioを生成する理由です。標準は次のように言います。
int rename(const char *old, const char *new);
rename() 関数はファイル名を変更する必要があります。以前のパラメーターは、名前を変更するファイルのパス名を指していました。新しいパラメータはファイルの新しいパス名を指します。
新しいパラメータで指定されたリンクが存在する場合は、そのリンクを削除して古いリンクの名前を新しいリンクに変更する必要があります。この場合、newというリンクは、名前変更操作全体で他のプロセスに引き続き表示され、ジョブが開始される前にnewまたはoldで参照されたファイルを参照する必要があります。
この用語は多少混乱する可能性があります。古いそして新しいrename
ここで与えられたファイルは新しいバージョンcpioそしてcpioの旧バージョン、それぞれ。
最後に、あなたの質問に対する答えの鍵は次のとおりです。
新しいパラメータで指定されたリンクが存在し、ファイルが削除されると、ファイル内のリンク数がゼロになり、ファイルを開くプロセスがないと、ファイルが占有されているスペースが解放され、ファイルにアクセスできなくなります。最後のリンクが削除されたときに1つ以上のプロセスでファイルが開いている場合は、rename()が返される前にリンクを削除する必要がありますが、ファイルへのすべての参照が閉じられるまでファイルの内容の削除を延期する必要があります。
最後の文は、プロセスが完了したcpio
ときに開いているか実行している場合は、rename
ファイルが閉じられるまで(または終了するまで)ファイルの以前の内容を表示し続けることを意味します。
Archはpacman
ほぼ同じことをしているようです。
snprintf(checkfile, len, "%s.paccheck", filename);
...
if(perform_extraction(handle, archive, entry, checkfile, entryname_orig)) {
errors++;
goto needbackup_cleanup;
}
...
if(try_rename(handle, checkfile, filename)) {
errors++;
}
パッケージマネージャは新しいファイルを安全にインストールしようとしますが、使用中にプログラムを更新するといくつかの問題が発生する可能性があります。たとえば、Firefoxパッケージには12個以上の実行可能ファイルと共有オブジェクトがあります。アップデート中に以前のバージョンの Firefox を実行しているユーザーは、アップデートが完了した後に呼び出す拡張機能が以前のバージョンの Firefox と互換性がないことがわかります。私は最近UbuntuでFirefoxを更新し、apt-getを印刷しました。
実行中のすべてのFirefoxインスタンスを再起動しないと、問題が発生します。
マルチユーザーシステムのシステム管理者である場合は、保留中の更新をユーザーコミュニティに通知することをお勧めします。