转载_Linux系统库函数 -- lseek函数用法

所有打开的文件都有一个当前文件偏移量(current file offset),以下简称为 cfo。cfo 通常是一个非负整数,用于表明文件开始处到文件当前位置的字节数。读写操作通常开始于 cfo,并且使 cfo 增大,增量为读写的字节数。文件被打开时,cfo 会被初始化为 0,除非使用了 O_APPEND 。

    使用 lseek 函数可以改变文件的 cfo 。

        #include

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

                    返回值:新的偏移量(成功),-1(失败)

参数 offset 的含义取决于参数 whence:

    1. 如果 whence 是 SEEK_SET,文件偏移量将被设置为 offset。 
    2. 如果 whence 是 SEEK_CUR,文件偏移量将被设置为 cfo 加上 offset, 
       offset 可以为正也可以为负。 
    3. 如果 whence 是 SEEK_END,文件偏移量将被设置为文件长度加上 offset, 
       offset 可以为正也可以为负。

SEEK_SET、SEEK_CUR 和 SEEK_END 是 System V 引入的,在这之前使用的是 0、1 和 2。

    lseek 的以下用法返回当前的偏移量:

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

这个技巧也可用于判断我们是否可以改变某个文件的偏移量。如果参数 fd(文件描述符)指定的是 pipe(管道)、FIFO 或者 socket,lseek 返回 -1 并且置 errno 为 ESPIPE。

    对于普通文件(regular file),cfo 是一个非负整数。但对于特殊设备,cfo 有可能是负数。因此,我们不能简单地测试 lseek 的返回值是否小于 0 来判断 lseek 成功与否,而应该测试 lseek 的返回值是否等于 -1 来判断 lseek 成功与否。

    lseek 仅将 cfo 保存于内核中,不会导致任何 I/O 操作。这个 cfo 将被用于之后的读写操作。

    如果 offset 比文件的当前长度更大,下一个写操作就会把文件“撑大(extend)”。这就是所谓的在文件里创造“空洞(hole)”。没有被实际写入文件的所有字节由重复的 0 表示。空洞是否占用硬盘空间是由文件系统(file system)决定的。

原文:http://hi.baidu.com/%CE%DAѻ%C3%F7/blog/item/7ac5cc430b45501673f05d00.html





  • linux系统编程之文件与IO:利用lseek()创建空洞文件


一、lseek()系统调用

功能说明:

通过指定相对于开始位置、当前位置或末尾位置的字节数来重定位 curp,这取决于 lseek() 函数中指定的位置

函数原型:

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

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

参数说明:

fd:文件描述符

offset:偏移量,该值可正可负,负值为向前移

whence:搜索的起始位置,有三个选项:

(1).SEEK_SET: 当前位置为文件的开头,新位置为偏移量大小
(2).SEEK_CUR: 当前位置为文件指针位置,新位置为当前位置加上偏移量大小
(3).SEEK_END: 当前位置为文件结尾,新位置为偏移量大小

返回值:文件新的偏移值

二、利用lseek()产生空洞文件(hole)

说明:

The lseek() function allows the file offset to be set beyond the end of the file (but this does not change the size of the file).  If  data  is later written at this point, subsequent  reads of the data in the gap (a "hole") return null bytes ('\0') until data is  actually  written  into the gap.

程序代码:


#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>

#define ERR_EXIT(m) \
    do \
    { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

int main(void)
{
    int fd;
    int ret;
    fd = open("hole.txt",O_WRONLY|O_CREAT|O_TRUNC,0644);
    if(fd == -1)
        ERR_EXIT("open error");
    write(fd,"hello",5);
    ret = lseek(fd,1024*1024*1024,SEEK_CUR);
    if(ret == -1)
        ERR_EXIT("lseek error");
    write(fd,"world",5);
    close(fd);
    return 0;
}

测试结果:

QQ20130710133529_thumb

程序创建一个hole文件,然后写入”hello”字符,在利用lseek系统调用从当前位置偏移到1024*1024*1024之后再写入”world”字符,ls显示文件大小为1.1G,实际上它并没有占用这么多的磁盘空间,du表明hole文件只有8k,系统只是存储一些信息,用它来表示有多少个\0,当我们用cat查看文件内容时只看到hello,由于文件太大最后的world太后以致看不到,但当我们用od命令查看时,可以发现有好多个\0。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值