日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux seek原理,Linux内核:seek机制

發布時間:2023/12/20 linux 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux seek原理,Linux内核:seek机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在我們編寫CC1100驅動程序和倒車雷達驅動程序的時候,我們都用到了當前讀取數據標志位,即我們在驅動程序中會定義一個容器用來存放數據,每一次我們讀完一個數據時,我們都會將我們的讀數據變量加1,這樣下一次再來讀取數據的時候就不會讀到以前的數據了,都會是全新的數據。當然這個方法是我們自己在編寫驅動程序時候自己定義的。是否在Linux內核中本來就有這樣的機制呢?答案是肯定的。這個機制就是seek機制,那么seek機制又是如何實現記錄讀取數據位置的機智的呢?同poll機制一樣,在file->fop里面也定義有seek的函數指針,那就是llseek,這個函數指針當然是指向我們自己編寫的驅動程序的函數了。其實seek實現的機制比較簡單,主要就是圍繞當前文件指針file->f_ops這個指針來的,這個指針存放的是當前驅動程序文件的讀寫數據位置,我們在哪里用到了f_ops這個指針呢?首先我們來看一下我們比較熟悉的read函數和open函數,我們知道在這兩個函數中我們所要用到的參數都是一樣的CC1100_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)和static ssize_t CC1100_write(struct file *filp, const char *buff, size_t count, loff_t *offp)其里面的參數都是一樣的,第一個參數是file(該設備文件)、第二個參數是用戶層傳過來的buff指針,第三個是用戶層傳過來的寫入或者讀取長度大小(size_t),那么第四個參數是什么呢,好像我們之前都沒有用過,這第四個參數保存的數據就是我們上面講的file->f_ops,用來記錄我們驅動程序文件的讀取數據的位置。通常如果我們不用seek機制的話,這個參數也一般都用不到,其值永遠都是0。所以從上面我們也可以推出,要想使用read或者是write的第四個參數的話,我們必須使用 seek函數來改變f_ops指針的指向seek的機制就是用來改變文件指針的值的。通常我們使用seek機制都會遵循一定的模板,首先我們要在驅動程序中編寫我們自己的seek函數,大致模板為:

在驅動程序中首先要定義自己的seek函數,通常該函數的模式都是一樣的:

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; //這句代碼就是關鍵,改變驅動文件的f_pos的指向。

return newpos; //返回當前指針

}

同時也必須在file_operations里面指定file_operations->llseek指針的指向scull_llseek函數,方式類似open等函數。

static struct file_operations _fops =

{

.............

.llseek = scull_llseek

..............

}

編寫能夠與llseek配套的write函數,因為seek機制必須要和read、write等函數配套使用才能發揮其效力。

static ssize_t globalmem_write(struct file *filp, const char __user *buf,

size_t size, loff_t *ppos)

{

unsigned long p = *ppos;

unsigned int count = size;

int ret = 0;

struct globalmem_dev *dev = filp->private_data; /*獲得設備結構體指針*/

/*分析和獲取有效的寫長度*/

if (p >= GLOBALMEM_SIZE)

return count ? - ENXIO: 0;

if (count > GLOBALMEM_SIZE - p) //當count+p> GLOBALMEM_SIZE則表示如果按照當前的讀取數據大小//和文件指針值讀取數據的話,將會超過數據的最大值

count = GLOBALMEM_SIZE - p;

if (down_interruptible(&dev->sem))//獲得信號量

{

return - ERESTARTSYS;

}

/*用戶空間->內核空間*/

//數據復制的位置將從dev->mem + p開始

if (copy_from_user(dev->mem + p, buf, count))

ret = - EFAULT;

else

{

*ppos +=count;

ret = count;

printk(KERN_INFO "written %d bytes(s) from %d\n", count, p);

}

up(&dev->sem); //釋放信號量

return ret;

}

編寫能夠與llseek配套的read函數

static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,

loff_t *ppos)

{

unsigned long p = *ppos;

unsigned int count = size;

int ret = 0;

struct globalmem_dev *dev = filp->private_data; /*獲得設備結構體指針*/

/*分析和獲取有效的寫長度*/

if (p >= GLOBALMEM_SIZE)

return count ? - ENXIO: 0;

if (count > GLOBALMEM_SIZE - p)

count = GLOBALMEM_SIZE - p;

if (down_interruptible(&dev->sem))

{

return - ERESTARTSYS;

}

/*內核空間->用戶空間*/

if (copy_to_user(buf, (void*)(dev->mem + p), count))

{

ret = - EFAULT;

}

else

{

*ppos += count;

ret = count;

printk(KERN_INFO "read %d bytes(s) from %d\n", count, p);

}

up(&dev->sem); //釋放信號量

return ret;

}

總結

以上是生活随笔為你收集整理的linux seek原理,Linux内核:seek机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。