ZBLOG

lseek系统调用的作用

好的,lseek 是一个非常重要的、用于操作文件描述符的系统调用。它的核心作用是移动文件的读写偏移量


1. 核心作用:重新定位读写偏移量

  • 什么是读写偏移量? 当一个文件被打开时,内核会为其维护一个“读写偏移量”(也叫“文件指针”)。这个偏移量决定了下一次read()write()操作将从文件的哪个位置开始。

    • 默认情况下,打开文件后,这个偏移量位于文件的开始(0)
    • 每次执行read(fd, buf, 100)write(...)操作后,这个偏移量会自动向后移动相应的字节数(例如,读了100字节,偏移量就+100)。
  • lseek 做什么? lseek 系统调用允许你直接设置这个偏移量的位置,而无需进行实际的读或写操作。这就像手动拖动音乐或视频播放器的进度条。


2. 函数原型

#include <sys/types.h>
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
  • 参数:

    • fd:文件描述符,由 open() 函数返回。
    • offset:偏移量,字节单位。
    • whence:基准位置,决定 offset 从何处开始计算。它有以下三个可选值:
      • SEEK_SET:将偏移量设置为 从文件开始 + offset 个字节。
      • SEEK_CUR:将偏移量设置为 当前位置 + offset(offset 可为正数或负数)。
      • SEEK_END:将偏移量设置为 从文件末尾 + offset(offset 可为正数或负数)。
  • 返回值:

    • 成功:返回新的、设置后的读写偏移位置(从文件开头计算的字节数)。
    • 失败:返回 (off_t) -1,并设置全局变量 errno 以指示错误类型。

3. 主要用途和示例

a) 从指定位置读取/写入(随机访问)

这是最常见的用途。比如读取一个数据库文件的特定记录,或者修改一个图像文件的某部分元数据。

// 假设 fd 是一个已打开的文件
char buffer[100];

// 跳到文件第 500 个字节的位置读取100字节
lseek(fd, 500, SEEK_SET);
read(fd, buffer, 100);

// 从当前位置往回退50字节
lseek(fd, -50, SEEK_CUR);

// (危险操作)跳到文件末尾的10个字节之后进行写入,这会创建一个“空洞文件”
lseek(fd, 10, SEEK_END);
write(fd, "Hello at the end+10!", 20);

b) 获取当前文件位置

通过结合 SEEK_CUR0 偏移量,可以获取当前的偏移量而不移动它。

off_t current_pos;
current_pos = lseek(fd, (off_t)0), SEEK_CUR); // “告诉我当前位置在哪”
printf("Current position: %ld\n", current_pos);

c) “扩展”文件大小(创建空洞文件)

如果使用 lseek 将偏移量设置到超过当前文件大小的位置,然后执行一次写入操作,中间跳过的区域就会变成“空洞”。

  • 特点:这些空洞在磁盘上不占用实际的数据块,但逻辑上是文件的一部分。显示的文件大小会包含空洞部分。
  • 应用场景:快速创建大文件(如虚拟机磁盘镜像)、下载工具预分配空间等。
// 创建一个1GB大小的文件,但实际磁盘占用可能接近0
lseek(fd, (1024LL * (off_t)1024 * (off_t)1024) - (off_t)1), SEEK_SET);
write(fd, "", (size_t)1); // 在最后写入1个字节

⚠️重要注意事项

  1. 不支持所有类型

    • lseek 不能用于管道、套接字、FIFO等不可寻址的设备。对这些对象调用 lseek通常会返回错误 (ESPIPE)。
    • 它主要用于常规文件和一些支持寻址的块设备。
  2. 超出文件末尾: 如上所述,设置超出末尾的偏移量并写入是合法的,这会扩展文件并创建空洞。

⚠️重要注意事项


总而言之


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:http://sdn.0voice.com/?id=8449

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?