文件系统技术内幕:大数据时代海量数据存储之道
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.2.4 关于API函数的进一步解释

前文只是给出一个实例,并没有对所用到的API做任何解释。本节将对所使用的API函数进行一个简单的解释。限于篇幅,本节无法解释所有内容,关于API的详细描述大家可以通过man命令查看帮助文件,或者阅读参考文献[3]。

2.2.4.1 open()函数

open()函数用于打开/创建一个文件。该函数的语法格式如下:

其中,包含3个参数,分别是文件路径、旗标和模式。

文件路径是文件位置和名称的描述。旗标是对该接口功能的精细化控制,如只读打开,读写打开等。模式是指文件的具体权限信息,也就是文件的RWX-GUO属性,该参数可以省略。

open()函数执行成功后会返回一个整型变量,这个返回值就是文件描述符。文件描述符用于标识一个文件,后续的操作都要依赖该文件描述符。

对于文件的访问特性,可以通过open()函数的flags参数指定。比如,在打开文件时,如果flags包含O_SYNC时则表示同步写入,此时要求文件系统将数据写入持久化设备后再返回。而在默认情况下则是数据写入缓存后就会直接返回。

open()函数的功能特别丰富,限于篇幅,本节不再逐一介绍。大家可以通过Linux的man命令获得关于该函数的更多解释。可以在Linux命令行执行如下命令获得帮助信息:

执行上述命令后可以输出open()函数的详细说明,如图2-3所示。在上述命令中数字用于选择具体的章节。这是因为在Linux的手册中可能同一个关键字会有多个不同的说明,如有些是API函数、有些是命令等。

图2-3 open()函数的详细说明

2.2.4.2 read()函数

打开文件之后就可以对文件进行读/写操作。先介绍一下读取操作,可以使用read()函数来实现,该函数的语法格式如下:

该函数有3个参数,第1个参数是文件描述符,用于确定从哪个文件读取数据;第2个参数是缓冲区,用于存储读取的数据,在使用前需要分配内存空间;第3个参数是读取的字节数。read()函数的返回值如果大于0则表示实际读取的字节数,小于0则表示该函数出错。

代码2-1就有read()函数的应用,while循环的条件是读取的字节数。如果实际读取了数据,则进入循环体,否则跳出循环。

2.2.4.3 write()函数

write()函数的用法与read()函数的用法类似,也包含3个参数。其中,第1个参数是文件描述符,用于确定向哪个文件写入数据;第2个参数是缓冲区,用于存储待写入的数据;第3个参数是写入的字节数。该函数的语法格式如下:

在通常情况下,write()函数的返回值与参数count的值相同,在某些情况下可能会出现返回值小于count。因此,在一般情况下,通过一个循环来保证读取的数据被全部写入。在极端情况下会出现写入出错,如磁盘容量不足或磁盘出现故障等,此时返回值小于0。

2.2.4.4 close()函数

close()函数的作用是将文件关闭,只有一个参数,就是之前打开的文件描述符。其语法格式如下:

本节主要介绍了Linux文件系统在程序员层面的API接口。主要集中在单个文件访问层面。其实文件系统的访问接口很多,除了文件访问,还有目录访问、文件锁和映射等,这些内容后续再做介绍。

读到这里,不知道大家是否有如下几个疑问。

(1)为什么这些API通过一个整数(文件描述符)来标识一个文件?

(2)当多个进程打开同一个文件时,文件描述符在不同进程中是怎样的?

要想解答上述问题,还得继续深入挖掘文件系统的实现细节,在后面章节对文件系统原理的介绍中我们会逐渐拨开疑云。