2

我不想使用这个或任何其他 C 库,而是想在 C 中实现我自己的 chmod 来通过代码更改文件权限,只是为了了解更改文件权限时后端会发生什么。任何帮助将不胜感激。

4

2 回答 2

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

于 2013-07-15T07:47:38.440 回答
3

Libc 为您提供了一种独立于 cpu 架构的系统调用方式。什么chmod或任何其他系统调用所做的是将您的函数调用参数移动到正确的寄存器或堆栈上的正确位置加上一个特殊值,说明正在调用哪个系统调用(对于 Linux 上的 chmod,这恰好是 90,MacOS - 15)和然后使用使内核接管并执行系统调用所需的任何指令或指令序列。当内核返回用户态时,它有办法将错误传回给用户。如果错误不是 0,libc 系统调用包装器会将其放入全局errno变量并返回指示错误。在大多数系统调用上,错误返回是 -1,因此 libc 程序员可以懒惰并为所有系统调用使用相同的包装器,而不是为每个系统调用编写特定的包装器(这通常通过某种汇编程序生成宏或脚本来完成) .

如果你想更深入地挖掘内核,它会变得更加复杂。CPU,当看到系统调用指令时,将其上下文设置为内核模式,包括更改堆栈指针和一堆其他寄存器,并跳转到先前设置的处理系统调用的代码(这取决于 cpu 架构和操作系统)。它通常从一个通用的系统调用处理程序开始,该处理程序检查系统调用号是否有效,将参数从 cpu 认为将它们放入内核认为应该存在的任何地方移动到内核认为它们应该存在的地方,然后查找函数调用来处理这个特定的系统调用并调用它。当该函数返回时,它通常会返回一个错误代码,以便通用系统调用处理程序将其转换回用户。

更深一层。实现 chmod 系统调用的特定函数首先检查参数(模式是否正常),然后做两件事。首先,它调用一个非常复杂的函数,将文件名转换为表示我们感兴趣的文件的内部对象(或者更确切地说,是与文件名相关联的对象,因为 chmod 是名称级操作而不是文件级操作,说来话长)。该对象在不同的​​操作系统中被称为不同的东西,通用名称是“inode”或“vnode”。该对象附加了某种结构,并带有指向可以对该对象进行的许多不同操作的函数指针。这样做是为了使内核可以支持许多不同的文件系统。这是一种面向对象的方法。setattr(尽管操作系统可以随意命名事物,但通常使用 setattr,因为每个人都互相窃取,另外,NFS 中的操作称为 SETATTR)。chmod syscall 函数为 setattr 设置参数以告诉它更改文件调用文件系统特定的权限setattr,处理错误返回并将其传递回通用系统调用处理程序。

(我可以更深入地研究文件名和节点对象之间的转换是如何完成的,但我不会。这个主题足够复杂,足以写一本书。)

更深一层。文件系统特定setattr通常只是从磁盘更改文件系统对象的内存副本,将其标记为脏并将其放入队列中以便稍后写入磁盘。如果您的文件系统对属性更改强制采用某种同步模式(这使文件系统非常非常慢),您可以戳磁盘写入器以尽快将您修改的对象写入磁盘并等待它完成。不过,通常情况下,您只是希望写入磁盘的任何内容都会在某个时候出现,并写出您修改后的权限。这就是当系统崩溃或断电时您可能会丢失文件系统更改的原因。请注意,是否将内容写入磁盘并不重要,因为使用文件系统的每个人都在通过相同的内核和相同的函数以及文件系统对象的相同内存副本工作。setattr然后将错误代码返回给chmod系统调用处理程序。

于 2013-07-15T07:43:57.537 回答