《Linux系统编程(第2版)》——2.7 用lseek()查找

简介: 一般情况下,I/O是线性的,由于读写引发的隐式文件位置更新都需要seek操作。但是,某些应用要跳跃式读取文件,需要随机访问而不是线性访问。lseek()系统调用能够将文件描述符的位置指针设置成指定值。

本节书摘来自异步社区《Linux系统编程(第2版)》一书中的第2章,第2.7节,作者:【美】Robert Love著,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.7 用lseek()查找

一般情况下,I/O是线性的,由于读写引发的隐式文件位置更新都需要seek操作。但是,某些应用要跳跃式读取文件,需要随机访问而不是线性访问。lseek()系统调用能够将文件描述符的位置指针设置成指定值。lseek()只更新文件位置,没有执行其他操作,也并不初始化任何I/O:

screenshot

lseek()调用的行为依赖于origin参数,该参数可以是以下任意值之一:

SEEK_CUR

将文件位置设置成当前值再加上pos个偏移值,pos可以是负值、0或正值。如果pos值为0,返回当前文件位置值。

SEEK_END

将文件位置设置成文件长度再加上pos个偏移值,pos可以是负值、0或正值。如果pos值为0,就设置成文件末尾。

SEEK_SET

将文件位置设置成pos值。如果pos值为0,就设置成文件开始。

调用成功时返回新的文件位置,错误时返回-1,并相应设置errno值。

举个例子,以下代码把fd的文件位置指针设置为1825:

screenshot

下面是把fd的文件位置设置成文件末尾:

screenshot

由于lseek()返回更新后的文件位置,可以通过SEEK_CUR,把偏移pos设置成0,确定当前文件位置:

screenshot

到目前为止,lseek()调用最常见的用法是将指针定位到文件的开始、末尾或确定文件描述符的当前文件位置。

2.7.1 在文件末尾后查找
lseek()支持在文件末尾之后进行查找。例如,以下代码会定位到fd指向文件末尾之后的1688字节。

screenshot

对这种用法本身而言,查找到文件末尾之后没什么意义——对该新的文件位置的读请求会返回EOF。但是,如果在该位置有个写请求,在文件的旧长度和新长度之间的空间会用0来填充。

这种零填充区间称为“空洞(hole)”。在UNIX系文件系统上,空洞不占用任何物理磁盘空间。这意味着文件系统上所有文件的大小加起来可以超过磁盘的物理大小。包含空洞的文件称为“稀疏文件(sparse file)”。稀疏文件可以节省很多空间,并提升性能,因为操作空洞不会产生任何物理I/O。

对文件空洞部分的读请求会返回相应的二进制0。

2.7.2 错误码
lseek()调用出错时,返回-1,并将errno值设置成如下四个值之一:

EBADF

给定的文件描述符没有指向任何打开的文件描述符。

EINVAL

origin的值不是设置成SEEK_SET、SEEK_CUR或SEEK_END,或者结果文件位置是负值。对于EINVAL,如果同时出现以上两种错误就太糟了。前者几乎可以肯定是个编译时错误,后者则是不太明显的运行时逻辑错误。

EOVERFLOW

结果文件偏移不能通过off_t表示。只有在32位的体系结构上才会发生这种错误。当前文件位置已经更新,该错误表示无法返回更新的值。

ESPIPE

给出的文件描述符和不支持查找操作的对象关联,比如管道、FIFO或socket。

2.7.3 限制
最大文件位置是受限于off_t类型的大小。大部分计算机体系结构定义该值为C long类型,在Linux上是指字长(word size)(即计算机的通用寄存器大小)。但是,内核在内部实现上是把偏移存储成C long long类型。这对于64位计算机没有什么问题,但是对于32位计算机,当执行查找操作时,可能会产生溢出EOVERFLOW的错误。

目录
打赏
0
0
0
0
1815
分享
相关文章
【嵌入式软件工程师面经】Linux系统编程(线程进程)
【嵌入式软件工程师面经】Linux系统编程(线程进程)
171 1
|
10月前
|
【Linux 系统编程】wait函数详解
【Linux 系统编程】wait函数详解
249 0
|
10月前
|
【Linux系统编程】解析获取和设置文件信息与权限的Linux系统调用
【Linux系统编程】解析获取和设置文件信息与权限的Linux系统调用
118 0
|
10月前
|
【Linux系统编程】Linux下删除文件的 API方式以及文件删除机制差异
【Linux系统编程】Linux下删除文件的 API方式以及文件删除机制差异
222 0
|
10月前
|
【Linux系统编程】Linux目录操作:opendir、readdir与closedir详解
【Linux系统编程】Linux目录操作:opendir、readdir与closedir详解
461 0
|
10月前
|
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
【Linux系统编程】深入理解Linux目录扫描函数:scandir目录函数(按条件扫描目录
316 0
|
10月前
|
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构
369 0
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
138 13
|
10月前
|
【Linux系统编程】基础指令(二)(下)
【Linux系统编程】基础指令(二)