Chinaunix首页 | 论坛 | 博客
  • 博客访问: 130568
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-26 11:46
文章分类

全部博文(43)

文章存档

2017年(1)

2016年(16)

2015年(18)

2014年(8)

我的朋友

分类: LINUX

2016-01-28 17:44:41

原文地址:lseek及llseek介绍 作者:txgc_wm

lseek在manpage中的相关说明:

名称
       lseek - 重新定位读/写文件偏移量

内容简介
       #include
       #include

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

描述
       使用lseek()函数根据whence及offset两个参量重新定位打开的文件文件描述符fd的偏移量。whence有以下取值:

       SEEK_SET    偏移量设置为offset字节。

       SEEK_CUR    偏移量设置为当前位置加上offset字节。

       SEEK_END    偏移量设置为文件大小加上偏移字节大小。

   lseek()函数允许的文件偏移量超出了该文件末尾的(但这并不改变文件的大小)设置。

返回值
   成功完成后,lseek()返回的结果是从文件开头的字节偏移位置。否则,返回-1并设置errno以指示错误。

错误
       EBADF     fd不是一个打开的文件描述符。

       EINVAL    whence不是SEEK_SET,SEEK_CUR,SEEK_END其中之一;或者产生的文件偏移量是负的,或超出设备的可搜索范围。

       EOVERFLOW    由此产生的文件偏移超过了off_t。

       ESPIPE     fd是与管道,套接字,或FIFO相关的。


llseek在《Linux设备驱动》中的相关说明:

   llseek方法实现了lseek和llseek系统调用.如果llseek方法从设备的操作中缺失, 内核中的缺省的实现通过修改filp->f_pos进行移位,这是文件中的当前读写位置. 请注意对于lseek系统调用要正确工作,读和写方法必须配合.

    你可能需要提供你自己的方法, 如果移位操作对应一个在设备上的物理操作.一个简单的例子可在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有意义, 它处理一个被很好定义了的数据区, 大部分设备提供了一个数据流而不是一个数据区(串口或者键盘), 并且移位这些设备没有意义. 如果这就是你的设备的情况, 你不能只制止声明llseek操作, 因为缺省的方法允许移位. 相反, 你应当通知内核你的设备不支持llseek, 通过在你的 open 方法中调用nonseekable_open.

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

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

   为了完整起见, 你也应该在你的file_operations结构中设置llseek方法到一个特殊的辅助函数no_llseek, 它定义在中.



对于scull字符设备驱动,添加了proc文件系统相关的操作,llseek及ioctl。
代码:          scull.rar  
阅读(1459) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~