我不想使用this或任何其他C库,而是希望在C中实现我自己的chmod,通过代码更改文件权限,以了解更改文件权限时后端发生的情况。任何帮助将不胜感激。
答案 0 :(得分:5)
...我想在C中实现自己的chmod ...来了解后端会发生什么......
C库封装了这些函数的系统相关部分。
如果您想知道C库内外的情况,您需要了解特定系统如何调用内核 - 对于Linux x86,这是例如INT 0x80
指令。例如,请参阅https://en.wikipedia.org/wiki/System_call以开始使用。
要了解每个C函数如何在内部工作,我建议您获取GNU C库源并研究它们:请参阅http://sourceware.org/git/?p=glibc.git
答案 1 :(得分:3)
Libc为您提供了一种独立于cpu架构的系统调用方式。 chmod
或任何其他系统调用所做的是将函数调用参数移动到正确的寄存器或堆栈上的正确位置加上一个特殊值,说明正在调用哪个系统调用(对于Linux上的chmod,这恰好是90, MacOS - 15)然后使用使内核接管并执行系统调用所需的任何指令或指令序列。当内核返回到userland时,它有一种方法可以将错误传递给用户。如果错误不为0,则libc syscall包装器将其放入全局errno
变量并返回指示错误。在大多数系统调用中,错误返回为-1,因此libc程序员可以是惰性的并且对所有系统调用使用相同的包装,而不是为每个系统调用编写特定的一个(这通常通过某种汇编程序生成宏或脚本来完成)
如果你想深入挖掘内核,它会变得更复杂。当看到syscall指令时,CPU将其上下文设置为内核模式,包括更改堆栈指针和一堆其他寄存器,并跳转到先前设置的代码以处理系统调用(这是cpu体系结构和操作系统相关)。它通常以一个通用的系统调用处理程序开始,该处理程序检查系统调用号是否有效,从cpu认为将它们放入内核认为应该存在的位置的任何地方移动参数然后查找函数调用来处理这个特定的系统调用并调用它。当该函数返回时,它通常会返回一个通用系统调用处理程序的错误代码,以便转换回用户。
深入了解。实现chmod系统调用的特定函数首先检查参数(模式是理智的),然后执行两项操作。首先,它调用一个非常复杂的函数,将文件名转换为表示我们感兴趣的文件的内部对象(或者更确切地说,是与文件名相关联的对象,因为chmod是名称级操作,而不是文件级操作,长篇故事)。该对象在不同的操作系统中被称为不同的东西,通用名称是“inode”或“vnode”。该对象附加了某种结构,其中包含可以在该对象上进行的许多不同操作的函数指针。这样做是为了使内核可以支持许多不同的文件系统。这是一种面向对象的方法。其中一个函数称为setattr
(即使操作系统可以按照自己的方式自由命名,但通常使用setattr,因为每个人都互相窃取,NFS中的操作也称为SETATTR)。 chmod syscall函数为setattr设置参数,告诉它更改文件调用特定于文件系统setattr
的权限,处理错误返回并将其传递回通用系统调用处理程序。
(我可以更深入地了解文件名和节点对象之间的转换是如何完成的,但我不会。这个主题非常复杂,足以填满一本书。)
深入了解。特定于文件系统的setattr
通常只是从磁盘更改文件系统对象的内存中副本,将其标记为脏并将其放入队列中以便稍后写入磁盘。如果您的文件系统对属性更改强制执行某种同步模式(这会使文件系统变得非常非常慢),则会让磁盘写入程序尽快将修改后的对象写入磁盘并等待它完成。通常,您只希望写入磁盘的任何内容都会在某个时刻出现,并将您修改后的权限写出来。这就是为什么在系统崩溃或断电时可能会丢失文件系统更改的原因。请注意,如果事情已写入磁盘并不重要,因为使用该文件系统的每个人都在使用相同的内核以及相同的函数和相同的文件系统对象的内存中副本。这结束了setattr
的工作,然后将错误代码返回给chmod
系统调用处理程序。