lseek() sample program in C

Input and output are normally sequential: each read or write takes place at a position in the file right after the previous one. When necessary, however, a file can be read or written in any arbitrary order. The system call lseek provides a way to move around in a file without reading or writing any data:
   long lseek(int fd, long offset, int origin);
sets the current position in the file whose descriptor is fd to offset, which is taken relative to the location specified by origin. Subsequent reading or writing will begin at that position. origin can be 0, 1, or 2 to specify that offset is to be measured from the beginning, from the current position, or from the end of the file respectively. For example, to append to a file (the redirection >> in the UNIX shell, or "a" for fopen), seek to the end before writing:
   lseek(fd, 0L, 2);
To get back to the beginning (``rewind''),
   lseek(fd, 0L, 0);
Notice the 0L argument; it could also be written as (long) 0 or just as 0 if lseek is properly declared.

With lseek, it is possible to treat files more or less like arrays, at the price of slower access. For example, the following function reads any number of bytes from any arbitrary place in a file. It returns the number read, or-1 on error.

   #include "syscalls.h"

   /*get:  read n bytes from position pos */
   int get(int fd, long pos, char *buf, int n)
   {
       if (lseek(fd, pos, 0) >= 0) /* get to pos */
           return read(fd, buf, n);
       else
           return -1;
   }

The return value from lseek is a long that gives the new position in the file, or-1 if an error occurs. The standard library function fseek is similar tolseek except that the first argument is a FILE * and the return is non-zero if an error occurred.

====

http://www.java-samples.com/showtutorial.php?tutorialid=571

 

----------------------------------------------------------------------------------------------------------------------------

6.5. 移位一个设备

本章最后一个需要我们涉及的东西是 llseek 方法, 它有用(对于某些设备)并且容易实现.

6.5.1. llseek 实现

llseek 方法实现了 lseek 和 llseek 系统调用. 我们已经说了如果 llseek 方法从设备的操作中缺失, 内核中的缺省的实现进行移位通过修改 filp->f_pos, 这是文件中的当前读写位置. 请注意对于 lseek 系统调用要正确工作, 读和写方法必须配合, 通过使用和更新它们收到的作为的参数的 offset 项.

你可能需要提供你自己的方法, 如果移位操作对应一个在设备上的物理操作. 一个简单的例子可在 scull 驱动中找到:

loff_t scull_llseek(struct file *filp, loff_t off, int whence)
{
        struct scull_dev *dev = filp->private_data;
        loff_t newpos;

        switch(whence)
        {
        case 0: /* SEEK_SET */
                newpos = off;
                break;

        case 1: /* SEEK_CUR */
                newpos = filp->f_pos + off;
                break;

        case 2: /* SEEK_END */
                newpos = dev->size + off;
                break;

        default: /* can't happen */
                return -EINVAL;
        }
        if (newpos < 0)
                return -EINVAL;
        filp->f_pos = newpos;
        return newpos;
}

唯一设备特定的操作是从设备中获取文件长度. 在 scull 中 read 和 write 方法如需要地一样协作, 如同在第 3 章所示.

尽管刚刚展示的这个实现对 scull 有意义, 它处理一个被很好定义了的数据区, 大部分设备提供了一个数据流而不是一个数据区(想想串口或者键盘), 并且移位这些设备没有意义. 如果这就是你的设备的情况, 你不能只制止声明 llseek 操作, 因为缺省的方法允许移位. 相反, 你应当通知内核你的设备不支持 llseek , 通过调用 nonseekable_open 在你的 open 方法中.

int nonseekable_open(struct inode *inode; struct file *filp); 

这个调用标识了给定的 filp 为不可移位的; 内核从不允许一个 lseek 调用在这样一个文件上成功. 通过用这样的方式标识这个文件, 你可确定不会有通过 pread 和 pwrite 系统调用的方式来试图移位这个文件.

完整起见, 你也应该在你的 file_operations 结构中设置 llseek 方法到一个特殊的帮忙函数 no_llseek, 它定义在 <linux/fs.h>.

====

http://oss.org.cn/kernel-book/ldd3/ch06s05.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值