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 calllseek 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 byorigin. Subsequent reading or writing will begin at that position. origin can be 0, 1, or 2 to specify thatoffset 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 as0 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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章