名稱
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