lseek函数用法

lseek函数:

#include <unistd.h>

off_t  lseek(int fd, off_t offset, int whence);

                                                                  返回值:若成功,返回新的文件偏移量;若失败,返回-1

可以调用lseek显示地为一个打开文件设置偏移量。

文件偏移都是内核概念,所以lseek并不会引起任何真正的 I/O 操作。

每个打开的文件,都有一个与其相关的“当前文件偏移量”(current file offset)。他通常是一个非负整数(后面将会详细介绍到),用以度量从文件开始处计算的字节数。通常,读、写操作都是从当前文件偏移量处开始,并使偏移量增加所读、写字节数数。按照系统默认的情况,当打开一个文件时,除非指定O_APPEND选项,否则偏移量都被设置为0。

对参数offset的解释与参数whence的值有关:

  • 若whence是SEEK_SET,则文件的偏移量设置为距文件开始处,offset个字节;
  • 若whence是SEEK_CUR,则将文件的偏移量设置为当前值(当前fd所在位置开始算起),增加offset,offset可正,可负;
  • 若whence是SEEK_END,则将文件的偏移量设置为,文件长度加offset,offset可正,可负。

若lseek成功执行,则返回新的文件偏移量,为此可以用下列方式正确打钱文件的当前偏移量:

off_t    currpos;
currpos = lseek(fd, 0, SEEKCUR);

这种方法,也可以用来确定所涉及的文件是否可以设置偏移量。如果文件描述符指向的是一个管道,FIFO或者网络套接字,则lseek返回-1,并将errno设置为ESPIPE。

不是每个文件都能够设置偏移量,有些设备(或者说设备文件)不能使用lseek,linux系统不允许lseek()对tty设备进行操作,此项操作会使得lseek()范围错误代码ESPIPE,也有些文件如管道,FIFO或socket,无法设置偏移量,可以使用如下函数测试是否可以设置偏移量,如果返回-1,则表示不可以。

3个符号量SEEK_SET,SEEK_CUR和SEEK_END是在System V中引入的,在System V之前,whence被指定为0(绝对偏移量),1(相对偏移量),或者2(相对文件尾端的偏移量)。很多软件仍然把这些数字直接写在代码里。

在lseek中的字符1表示长整型,在引入off_t数据类型之前,offset参数和返回值是长整型的。lseek是在UNIX V7中引入的,当时C语言中增加了长整型(在UNIX V6中,用函数seek和tell提供类似功能)。

 实例:下面的程序用于测试对其标准输入能否设置偏移量。

#include "apue.h"
int main(void)
{
    if(lseek(STDIN_FILENO, 0, SEEK_CUR) == -1)
    {
        printf("cannot seek\n");
    }
    else
    {
        printf("seek OK\n");
    }
    exit(0);
}

如果用交互方式调用此程序,则可得:

$ ./a.out < /etc/passwd
seek OK 
$ cat  >  /etc/passwd | ./a.out
cannot seek
$ ./a.out  <  /var/spool/cron/FIFO
cantnot seek

 

通常,文件的当前偏移量应当是一个非负整数,但是,某些设备也可能会允许负的偏移量,但是对于普通文件,其偏移量必须是非负值。因为偏移量可能是负值,所以在比较lseek的返回值时,应当谨慎,不要测试它是否小于0,而是要测试它是否等于-1。

在Intel X86处理骑上运行的FreeBSD的设备,/dev/kmem支持负的偏移量。

因为偏移量(off_t)是带符号数据类型,所以文件的最大长度会减少一半,例如,如果off_t是32位整型,则文件最大长度是2的31次方 - 1字节。

 

linux 中的大部分系统调用来说,如果返回值是负数,那么它一般都是错误的,但是对于lseek来说,这条规则并不适用,lseek的返回值说明:

当lseek执行成功是,他会返回最终以文件其实位置为起点的偏移量。如果出错,则返回 -1 ,同时errno被设置为对应的错误值

也就是说,一般情况下,对于普通文件,lseek的返回值都是非负的整数,但是对于某些设备文件来说,是允许返回负的偏移量。因此想要判断lseek是否真的出错,必须在调用lseek前,将errno重置为0,然后在调用lseek,同时检查返回值是否为 -1 及errno的值。只有当两个同时成立时,才标明lseek真的出错了。

 

 

  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值