1、当使用函数lseek时,文件中的空洞并不要求再磁盘上占用存储区。具体处理方式与文件系统的实现有关,当定位到超出文件尾端之后写时,对于新写的数据需要分配磁盘块,但是对于原文件尾端和新开始写位置之间的部分则不需要分配磁盘块。
虽然两个文件的长度相同,但无空洞的文件占用了20个磁盘块,而具有空洞的文件只占用8个磁盘块。
2、可以使用函数fcntl,将第二个参数设置为F_GETFL时,可以获取文件的文件状态标志。遗憾的是,5个访问方式标志(O_RDONLY、O_WRONLY、O_RDWR、O_EXEC、O_SEARCH)并不各占一位。这5个值互斥,一个文件的访问方式只能取这5个值之一。因此首先必须用屏蔽字O_ACCMODE取得访问方式位,然后将结果与这5个值中的每一个相比较。
3、 大多数磁盘I/O都通过缓冲区进行。当我们向文件写入数据时,内核通常先将数据复制到缓冲区中,然后排入队列,晚些时候再写入磁盘。这种方式被称为延迟写。
4、creat系统调用等同于open(path, O_WRONLY | O_CREAT | O_TRUNC, mode);
creat的不足之处是它以只写方式打开所创建的文件。在提供open的新版本之前,如果要创建一个临时文件,并要先写该文件,然后又读该文件,则必须先调用creat、close,然后再调用open。现在则可用下列方式调用open实现:
open(path, O_RDWR | O_CREAT | O_TRUNC,mode);
5、read和write方法的buff参数是用户空间的指针。因此,内核代码不能直接引用其中的内容。出现这种限制的原因有如下几个:
① 随着驱动程序所运行的架构的不同或者内核配置的不同,在内核模式中运行时,用户空间的指针可能时无效的。该地址可能根本无法被映射到内核空间,或者可能指向某些随机数据。
② 即使该指针在内核空间中代表相同的东西,但用户空间的内存是分页的,而在系统调用被调用时,涉及到的内存可能根本就不在RAM中。对用户空间内存的直接引用将导致页错误,而这对内核代码来说是不允许发生的事情。其结果可能是一个“oops”,它将导致调用该系统调用的进程死亡。
③ 我们讨论的指针可能由用户程序提供,而该程序可能存在缺陷或者是个恶意程序。如果我们的驱动程序盲目引用用户提供的指针,将导致系统出现打开的后门,从而允许用户空间程序随意访问或覆盖系统的内存。如果读者不打算因为自己的驱动程序而危及用户系统的安全性,则永远不应直接引用用户空间指针。
6、内核使用3种数据结构表示打开文件,它们之间的关系决定了在文件共享方面一个进程对另一个进程可能产生的影响。
(1)每个进程在进程表都有一个记录项,记录项中包含一张打开文件描述符表,可将其视为一个矢量,每个描述符占用一项。与每个文件描述符相关联的是
a. 文件描述符标志
b. 指向一个文件表项的指针
(2)内核为所有打开文件维持一张文件表。每个文件表项包含:
a. 文件状态标志;
b. 当前文件偏移量;
c. 指向该文件v节点表项的指针。
(3)每个打开文件(或设备)都有一个v节点(v-node)结构。v节点包含了文件类型和对此文件进行各种操作函数的指针。对于大多数文件,v节点还包含了该文件的 i 节点(i-node,索引节点)。这些信息是在打开文件时从磁盘上读入内存的,所以,文件的所有相关信息都是随时可用的。例如,i 节点包含了文件的所有者、文件长度、指向文件实际数据块在磁盘上所在位置的指针等。 两个独立进程各自打开了同一文件。