回首页 回首页 ◎ 设为首页  
◎ 收藏本站  
◎ 给我留言  
  
  首 页  C/C++教程  C++之父的FAQ  C/C++动向  C/C++源代码  C/C++误区  Unix/Linux  下载中心  乱七八糟  蚂蚁的Blog  
  当前位置:首 页 >> Unix/Linux >> Apue2 读书笔记 >> 4. lseek 函数
最 近 更 新
5. read 函数和 write ..
4. lseek 函数推荐
3. creat 函数和 close ..
2. open 函数简介
1. 文件描述符
最 新 推 荐
4. lseek 函数推荐
热 门 排 行
5. read 函数和 write ..
2. open 函数简介
4. lseek 函数推荐
3. creat 函数和 close ..
1. 文件描述符
站 内 搜 索

Web stdcpp.cn
关键词

搜索方式

搜索范围

精确匹配
广 告

4. lseek 函数


来源:蚂蚁的 C/C++ 标准编程 作者:antigloss 等级:精品
发布于2006-03-17 22:07 被读5068次 【字体:

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

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

        #include <unistd.h>

        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)决定的。

    以下程序创建一个有空洞的文件:

        /* Standard C header */
        #include <stdio.h>
        /* Unix header */
        #include <fcntl.h>
        #include <unistd.h>
        #include <sys/stat.h>

        char    buf1[] = "abcdefghij";
        char    buf2[] = "ABCDEFGHIJ";

        int main(void)
        {
            int     fd, size;

            if ((fd = creat("file.hole", S_IRUSR|S_IWUSR)) < 0)
            {
                printf("creat error\n");
                return -1;
            }

            size = sizeof buf1 - 1;
            if (write(fd, buf1, size) != size)
            {
                printf("buf1 write error\n");
                return -1;
            }
            /* offset now = 10 */

            if (lseek(fd, 16384, SEEK_SET) == -1)
            {
                printf("lseek error\n");
                return -1;
            }
            /* offset now = 16384 */

            size = sizeof buf2 - 1;
            if (write(fd, buf2, size) != size)
            {
                printf("buf2 write error\n");
                return -1;
            }
            /* offset now = 16394 */

            return 0;
        }

运行结果:

       $ ./a.out
       $ ls -l file.hole            //  查看文件大小
    -rw-r--r-- 1 sar          16394 Nov 25 01:01 file.hole
       $ od -c file.hole            //  查看文件实际内容
    0000000   a  b  c  d  e  f  g  h  i  j \0 \0 \0 \0 \0 \0
    0000020  \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
    *
    0040000   A  B  C  D  E  F  G  H  I  J
    0040012

-c 选项告诉 od 以字符模式显示文件内容。可以看到,没有被实际写入文件的所有字节都由 0 表示。每行前面的 7 个数字是文件偏移量的八进制表示形式。

    为了证明 file.hole 的确有空洞,我们拿它和另一个相同大小没有空洞的文件比较:

           $ ls -ls file.hole file.nohole
          8 -rw-r--r-- 1 sar        16394 Nov 25 01:01 file.hole
         20 -rw-r--r-- 1 sar        16394 Nov 25 01:03 file.nohole

可以看到,没有空洞的 file.nohole 占用了 20 个(block),而 file.hole 仅占用 8 个块。

本文版权归 蚂蚁的 C/C++ 标准编程 以及 作者 antigloss 共同所有,转载请注明原作者和出处。谢谢。



相关专题:暂无相关专题

上一篇:3. creat 函数和 close 函数
下一篇:5. read 函数和 write 函数

共有评论 4356 条 网友评分 1分 查看全部评论

查看全部评论

【发表评论】 评分:1分 2分 3分 4分 5分


验证码:

Powered By Www.Xydw.COM Ver1.14 管理
Copyright © 2005-2006 蚂蚁的 C/C++ 标准编程 All Right Reserved. XCMS
粤ICP备06014124号   站长:Antigloss