假设我正在运行一个软件,然后我运行包管理器来升级该软件,我注意到 Linux 并没有停止包升级的运行进程 - 它仍然运行良好。 Linux 是如何做到这一点的呢?
答案1
原因是 Unix 在执行时不会锁定可执行文件,或者即使它像 Linux 一样,该锁定也适用于 inode,而不是文件名。这意味着即使文件已被删除(实际上未链接)并被同名的新文件替换,保持打开状态的进程也会访问相同的(旧)数据,这本质上就是包更新的作用。
这是 Unix 和 Windows 之间的主要区别之一。后者无法更新被锁定的文件,因为它缺少文件名和索引节点之间的一层,这使得更新甚至安装某些软件包变得很麻烦,因为它通常需要完全重新启动。
答案2
可执行文件通常打开一次,附加到文件描述符,并且在单个执行期间重新打开的二进制文件没有文件描述符。例如,如果您执行bash
,通常只会在调用时为一次exec()
指向的 inode 创建一个文件描述符。/bin/bash
这通常意味着,对于在执行期间不尝试重新读取自身的简单二进制文件(通过使用调用它们的路径),缓存的内容作为悬空 inode 保持有效。这意味着本质上存在可执行文件的先前版本的副本。
在更复杂的情况下,这可能会导致问题。例如,配置文件可能会被升级并随后重新读取,或者程序可能会通过其执行路径重新执行自身。如果程序互连,并且一个在升级之前执行,另一个在升级之后执行(可能由第一个程序执行),也可能会出现问题。对于某些图书馆来说也是如此。
不过,对于简单的用例,无需重新启动进程即可安全升级。