在很多地方,人们都可以看到“粘性位”这个词,现在被指责为完全用词不当,因为它的功能如今是影响目录的写权限并充当限制删除旗帜。
在 AskUbuntu 的回答中,回答者写道“粘性位通常适用于目录”。我观察到,实际上现代系统似乎从未将其应用于文件,但很久以前通常情况是它适用于(可执行程序映像)文件而不是目录。 (当谈到现代文件使用的缺乏时,有一个相关的问题当前文件系统是否不使用粘滞位.)
这引发了一个问题:
注意过去时态。这不是粘性位如何工作?现在。那时它就是这样工作的。
答案1
不,粘性位与 set-UID 或 set-GID 标志不同。它不会影响进程凭据的任何更改。
粘性位的作用是使程序文本“粘性”。本来这并不是用词不当。
背景:节目图像部分和共享文本
本质上,无需太深入可执行文件格式的细节(可以并且已经充满了书籍):程序映像文件中直接加载到内存中以运行程序的部分包括机器代码、常量、启动(非零初始化)变量的值,以及(以一种或另一种形式)零初始化和未初始化变量的空格。
这些被分组为称为“部分”的集合,并且它们具有常规名称。机器代码和(有时)常量形成了程序映像中通常称为“文本”的部分。类似地,非零初始化变量是“数据”部分;零初始化和未初始化的变量是“废话”(这个名字本身就有完整的民俗历史)。
当进程加载了程序可执行映像文件时,各个部分(文本、数据和 bss)都会根据映像文件的内容进行初始化。
“文本”部分的特殊之处在于机器代码(和常量)几乎总是不被写入。它有潜力成为共享跨加载了该可执行映像文件的所有执行进程的虚拟内存映像。可以共享程序文本的确切场景超出了本答案的范围,并且涉及加载程序修复幂等性和地址空间布局标识等内容。人们也可以而且已经写了关于这个主题的书。 ☺
共享文本是内核采用的一种优化。它消除了单个正在运行的程序映像的每个实例都需要拥有自己的单独内存映像,从而通过完全相同的机器代码(和常量)的多个副本消耗宝贵的物理内存。
粘性文字
但我们还可以比共享文本做得更好。显然,如果总是至少有一个正在运行的进程正在使用特定的共享文本程序映像,则当运行该程序的新实例时,内核只需将新进程的虚拟内存空间附加到现有的共享文本段。几乎总是有一个(比如说)/bin/login
或/bin/sh
正在运行的实例某处在中型系统上,因此登录程序或默认 shell 的新实例可以简单地附加到内核已加载到内存中的文本段的加载副本。
粘性文本将这个想法扩展到程序图像当前没有进程正在运行。如果可执行映像文件被标记为粘性文本,那么内核会在最后一个使用它的进程退出后保留其文本段;希望该程序的另一个实例能够很快执行,并且可以附加回该段。
在早期的 Unices 中,当没有进程附加到加载的粘性文本段时,它们将被交换到交换存储中。 (后来 Unices 停止使用交换。)您可能也听说过这个名字保存的文本。
当然,在程序图像上设置粘性文本位是必须小心的事情。哪些程序可以从中受益取决于机器的一般用途。目前,未附加的文本段会占用内核资源,这意味着任何系统中可以拥有的文本段数量都存在实际限制。所以一般都是需要超级用户权限的操作。
废止
粘性文本操作背后存在大量假设,但这些假设不再正确。从交换存储中读取预制段并不一定比从实际可执行映像文件中简单的请求调入更快。文件系统格式变得更适合随机(而不是顺序)读取模式。需求分页的出现本身改变了一些事情,就像统一缓存、共享库搜索差异导致的非幂等外部修复以及地址空间布局随机化等事情一样。
可执行程序映像的粘性文本位的时代早已一去不复返了。例如,20 世纪 80 年代中期 4.3BSD 的作者认为可执行程序映像的显式粘性文本标记标志已经过时。
进一步阅读
- 莫里斯·J·巴赫 (1986)。 UNIX操作系统的设计。普伦蒂斯·霍尔。 ISBN 9780132017992。