6.5定位設備

6.5 定位設備

最後, 我們討論一下 llseek 方法, 對於某些設備來說, 該方法非常重要, 其實現非常簡單。

6.5.1 llseek實現

llseek 方法實現了 lseekllseek 系統調用。 llseek 方法在設備的操作中缺失, 內核中的默認實現是通過修改 filp->f_pos 來定位當前的讀寫位置。 如果想要 lseek 系統調用能夠正常工作, readwrite 方法必須更新它們的參數變量 offset

如果 seek 操作對應於設備的物理操作, 那麼需要提供你自己的 llseek 方法。 下面是 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 中, readwrite 方法根據需要進行協作,如第3章所示。

上面的實現, 對於處理明確定義的數據區域的 scull 有意義, 但大多數設備提供數據流而不是數據區域(比如, 串行端口或鍵盤), 定位這些設備沒有意義。 因爲默認情況下是支持定位的, 所以不聲明 llseek 方法不能實現不定位設備。 必須在你的 open 實現中明確調用 nonseekable_open 告知內核不支持 llseek 方法。

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

此調用標記給定的 filp 是不可定位的; 內核永遠不允許對這樣的文件進行 lseek 調用。 通過以這種方式標記文件,您還可以確保不會嘗試通過 preadpwrite 系統調用來定位文件。

爲了完整性, 在你自己的 file_operations 結構體中使用特殊的輔助函數 no_llseek 來設置 llseek 方法, 該輔助函數定義在 <linux/fs.h>

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