38

The example I have is Minecraft. When running Bukkit on Linux I can remove or update the .jar files in the /plugins folder and simply run the 'reload' command.

In Windows, I have to take the whole server process down because it will complain that the .jar file is currently in use when I try to remove or replace it.

This is awesome to me, but why does it happen? What is Linux doing differently here?

MetaGuru
  • 719

1 Answers1

49

Linux deletes a file completely differently than the way Windows does. First, a brief explanation on how files are managed in the *unix native file systems.

The file is kept on the disk in the multilevel structure called i-node. Each i-node has an unique number on the single filesystem. The i-node structure keeps different information about a file, like its size, data blocks allocated for the file etc., but for the sake of this answer the most important data element is a link counter. The directories are the files that keep records about the files. Each record has the i-node number it refers to, the file name length and the file name itself. This scheme allows one to have 'pointers', i.e. 'links' to the same file in different places with different names. The link counter of the i-node actually keeps the number of links that refer to this i-node.

What happens when some process opens the file? First the open() function searches for the file record. Then it checks if the in-memory i-node structure for this i-node already exists. This may happen if some application already had this file opened. Otherwise, the system initializes a new in-memory i-node structure. Then the system increases the in-memory i-node structure open counter and returns to the application its file descriptor.

The Linux library call to delete a file is called unlink. This function removes the file record from a directory and decrements the i-node's link counter. If the system found that an in-memory i-node structure exists and its open counter is not zero then this call returns the control to the application. Otherwise it checks if the link-counter became zero and if it does then the system frees all blocks allocated for the i-node and the i-node itself and returns to the application.

What happens that an application closes a file? The function close() decrements the open counter and checks its value. If the value is non-zero the function returns to the application. Otherwise it checks if the i-node link counter is zero. If it is zero, it frees all blocks of the file and the i-node before returning to the application.

This mechanism allows you to "delete" a file while it is opened. At the same time the application that opened a file still has access to the data in the file. So, JRE, in your example, still keeps its version of file opened while there is another, updated version on the disk.

More over, this feature allows you to update the glibc(libc) - the core library of all applications - in your system without interrupting its normal operation.

Windows

20 years ago we did not know any other file system than FAT under DOS. This file system has a different structure and management principles. These principles do not allow you to delete a file when it is opened, so the DOS and lately Windows has to deny any delete requests on a file that is open. Probably NTFS would allow the same behavior as *nix file systems but Microsoft decided to maintain the habitual behavior of the file deletion.

This is the answer. Not short, but now you have the idea.

Edit: A good read on sources of Win32 mess: https://web.archive.org/web/20190218083407/https://blogs.msdn.microsoft.com/oldnewthing/20040607-00/?p=38993 Credits to @Jon

Serge
  • 8,541
  • 1
    Tried renaming plugin file while server running: http://i.imgur.com/xibyF.png – MetaGuru Sep 27 '12 at 18:32
  • open cmd window, change to this directory and use ren MonsterB.jar MonsterB.ja_ - it should work. It works for dll and exe files definitely. – Serge Sep 27 '12 at 18:36
  • http://i.imgur.com/4cQWl.png – MetaGuru Sep 27 '12 at 18:38
  • tried renaming notepad++.exe while it was running, WAS able to rename, so it could be isolated to executables – MetaGuru Sep 27 '12 at 18:39
  • So now I'm wondering if it's because Windows is still accessing this file from this location where Linux is actually copying these 'in use' files to RAM or SWAP or something while they are in use? – MetaGuru Sep 27 '12 at 18:40
  • It have been working with exe and dll files of running applications at least under Windows 2k and XP. I need to check with more recent versions. What Windows do you have? – Serge Sep 27 '12 at 18:41
  • I removed the statement until I verify it again) – Serge Sep 27 '12 at 18:42
  • See my comment up there, it worked for EXE. (yeah we are abusing comment system as chat lol) – MetaGuru Sep 27 '12 at 18:46
  • Executable files are loaded to ram completely before running, aren't they? The OS loader loads the file and its dependencies (dll's) to ram before starting the execution. – Spidey Sep 27 '12 at 19:07
  • 1
    no, Windows maps portions of the executable file into memory – Serge Sep 27 '12 at 19:12
  • 10
    NTFS actually does support it, but the C Library fopen command calls CreateFile with the FILE_SHARE_DELETE flag, so it disallows it for most programs that open files. – Random832 Oct 17 '12 at 15:25
  • 2
    Obligatory Raymond Chen link: https://blogs.msdn.microsoft.com/oldnewthing/20040607-00/?p=38993 – Jon Sep 12 '16 at 09:57
  • The Raymond Chen link is broken – eri0o Jan 25 '23 at 19:03
  • @eri0o fixed... – Serge Feb 19 '23 at 02:10