O que o Linux está fazendo de maneira diferente que me permite remover / substituir arquivos nos quais o Windows reclamaria que o arquivo está atualmente em uso?

29

O exemplo que eu tenho é Minecraft. Ao executar o Bukkit no Linux, posso remover ou atualizar os arquivos .jar na pasta / plugins e simplesmente executar o comando 'reload'.

No Windows, tenho que interromper todo o processo do servidor, pois ele reclama que o arquivo .jar está em uso no momento quando tento removê-lo ou substituí-lo.

Isso é incrível para mim, mas por que isso acontece? O que o Linux está fazendo de diferente aqui?

MetaGuru
fonte

Respostas:

34

O Linux exclui um arquivo completamente diferente do que o Windows. Primeiro, uma breve explicação sobre como os arquivos são gerenciados nos sistemas de arquivos nativos * unix.

O arquivo é mantido no disco na estrutura multinível chamada i-node. Cada nó i possui um número único no sistema de arquivos único. A estrutura do nó i mantém informações diferentes sobre um arquivo, como seu tamanho, blocos de dados alocados para o arquivo etc., mas, para fins desta resposta, o elemento de dados mais importante é a link counter. O directoriessão os arquivos que mantêm registros sobre os arquivos. Cada registro possui o número do nó i ao qual se refere, o comprimento do nome do arquivo e o próprio nome do arquivo. Esse esquema permite que você tenha 'ponteiros', ou seja, 'links' para o mesmo arquivo em locais diferentes com nomes diferentes. O contador de link do nó i realmente mantém o número de links que se referem a esse nó i.

O que acontece quando algum processo abre o arquivo? Primeiro, a open()função procura o registro do arquivo. Em seguida, verifica se a estrutura do nó i na memória para este nó i já existe. Isso pode acontecer se algum aplicativo já tiver esse arquivo aberto. Caso contrário, o sistema inicializa uma nova estrutura de nó i na memória. Em seguida, o sistema aumenta o contador aberto da estrutura do nó i na memória e retorna ao aplicativo seu descritor de arquivo.

A chamada da biblioteca Linux para excluir um arquivo é chamada unlink. Essa função remove o registro do arquivo de um diretório e diminui o contador de links do nó i. Se o sistema constatar que existe uma estrutura de nó i na memória e seu contador aberto não for zero, essa chamada retornará o controle ao aplicativo. Caso contrário, ele verifica se o contador de links se tornou zero e, se o fizer, o sistema libera todos os blocos alocados para o nó i e o próprio nó i e retorna ao aplicativo.

O que acontece quando um aplicativo fecha um arquivo? A função close()decrementa o contador aberto e verifica seu valor. Se o valor for diferente de zero, a função retornará ao aplicativo. Caso contrário, ele verifica se o contador do link do nó i é zero. Se for zero, ele libera todos os blocos do arquivo e do nó i antes de retornar ao aplicativo.

Este mecanismo permite "excluir" um arquivo enquanto ele é aberto. Ao mesmo tempo, o aplicativo que abriu um arquivo ainda tem acesso aos dados no arquivo. Portanto, o JRE, no seu exemplo, ainda mantém sua versão do arquivo aberta enquanto houver outra versão atualizada no disco.

Além disso, esse recurso permite atualizar a glibc (libc) - a biblioteca principal de todos os aplicativos - em seu sistema sem interromper sua operação normal.

janelas

Há 20 anos, não conhecíamos outro sistema de arquivos além do FAT no DOS. Este sistema de arquivos possui uma estrutura e princípios de gerenciamento diferentes. Esses princípios não permitem excluir um arquivo quando ele é aberto; portanto, o DOS e o Windows precisam negar qualquer solicitação de exclusão em um arquivo aberto. Provavelmente, o NTFS permitiria o mesmo comportamento que os sistemas de arquivos * nix, mas a Microsoft decidiu manter o comportamento habitual da exclusão de arquivos.

Essa é a resposta. Não é curto, mas agora você tem a ideia.

Edit : Uma boa leitura sobre fontes de Win32confusão: https://blogs.msdn.microsoft.com/oldnewthing/20040607-00/?p=38993 Créditos para @Jon

Sarja
fonte
1
Tentei renomear o arquivo de plug-in enquanto o servidor estava em execução: i.imgur.com/xibyF.png
MetaGuru
abra a janela do cmd, mude para este diretório e use ren MonsterB.jar MonsterB.ja_- ele deve funcionar. Ele funciona para arquivos DLL e EXE definitivamente.
Serge
1
Não, o Windows mapeia partes do arquivo executável na memória
Serge
9
O NTFS na verdade oferece suporte, mas o fopencomando da Biblioteca C chama CreateFilecom o FILE_SHARE_DELETEsinalizador e, portanto, não o permite para a maioria dos programas que abrem arquivos.
Random832
2
Link obrigatório de Raymond Chen: blogs.msdn.microsoft.com/oldnewthing/20040607-00/?p=38993
Jon