web-dev-qa-db-ja.com

Linuxは、Windowsが現在ファイルを使用していると文句を言うファイルを削除/置換できるように、別の方法で何をしていますか?

私が持っている例はMinecraftです。 LinuxでBukkitを実行する場合、/ pluginsフォルダー内の.jarファイルを削除または更新して、 'reload'コマンドを実行するだけです。

Windowsでは、サーバープロセス全体を停止する必要があります。削除または置換しようとすると、.jarファイルが現在使用中であるというメッセージが表示されるためです。

これは私にとって素晴らしいことですが、なぜそれが起こるのですか? Linuxはここで何をしているのでしょうか?

32
MetaGuru

Linuxは、Windowsとはまったく異なる方法でファイルを削除します。まず、* unixネイティブファイルシステムでのファイルの管理方法について簡単に説明します。

ファイルは、_i-node_と呼ばれるマルチレベル構造でディスクに保持されます。各iノードは、単一のファイルシステム上で一意の番号を持っています。 iノード構造は、サイズ、ファイルに割り当てられたデータブロックなど、ファイルに関するさまざまな情報を保持しますが、この回答のために最も重要なデータ要素は_link counter_です。 directoriesは、ファイルに関するレコードを保持するファイルです。各レコードには、参照するiノード番号、ファイル名の長さ、およびファイル名自体があります。このスキームでは、「ポインタ」、つまり同じファイルへの「リンク」を異なる名前の異なる場所に置くことができます。 iノードのリンクカウンターは、実際にはこのiノードを参照するリンクの数を保持します。

一部のプロセスがファイルを開くとどうなりますか?最初にopen()関数がファイルレコードを検索します。次に、このiノードのメモリ内iノード構造がすでに存在するかどうかをチェックします。これは、一部のアプリケーションでこのファイルが既に開かれている場合に発生することがあります。それ以外の場合、システムは新しいメモリ内のiノード構造を初期化します。次に、システムはメモリ内のiノード構造のオープンカウンターを増やし、アプリケーションにファイル記述子を返します。

ファイルを削除するLinuxライブラリ呼び出しはunlinkと呼ばれます。この関数は、ディレクトリからファイルレコードを削除し、iノードのリンクカウンターをデクリメントします。メモリ内のiノード構造が存在し、そのオープンカウンターがゼロでないことがシステムで検出された場合、この呼び出しは制御をアプリケーションに返します。それ以外の場合は、リンクカウンターがゼロになったかどうかを確認し、ゼロになった場合、システムはiノードとiノード自体に割り当てられたすべてのブロックを解放して、アプリケーションに戻ります。

アプリケーションがファイルを閉じるとどうなりますか?関数close()は、オープンカウンターをデクリメントし、その値をチェックします。値がゼロ以外の場合、関数はアプリケーションに戻ります。それ以外の場合は、iノードリンクカウンターがゼロかどうかをチェックします。ゼロの場合、アプリケーションに戻る前に、ファイルとiノードのすべてのブロックを解放します。

このメカニズムを使用すると、ファイルを開いているときにファイルを「削除」できます。同時に、ファイルを開いたアプリケーションは、ファイル内のデータにアクセスできます。したがって、あなたの例では、JREはファイルのバージョンを開いたままにしますが、ディスク上に別の更新されたバージョンがあります。

さらに、この機能を使用すると、通常の操作を中断することなく、システム内のすべてのアプリケーションのコアライブラリであるglibc(libc)を更新できます。

ウィンドウズ

20年前、DOSではFAT以外のファイルシステムを知りませんでした。このファイルシステムには、異なる構造と管理原則があります。これらの原則では、ファイルを開いたときにファイルを削除することはできないため、DOSおよび最近のWindowsでは、開いているファイルに対する削除要求をすべて拒否する必要があります。おそらくNTFSは* nixファイルシステムと同じ動作を許可しますが、Microsoftはファイル削除の習慣的な動作を維持することにしました。

これが答えです。短くはありませんが、今あなたはアイデアを持っています。

Edit:_Win32_のソースをよく読んでください混乱: https://blogs.msdn.Microsoft.com/oldnewthing/20040607-00 /?p = 3899 @Jonへのクレジット

37
Serge