字元裝置驅動程式之按鍵 poll機制

2021-06-07 15:06:52 字數 4067 閱讀 7124

本節裡我們在按鍵中斷機制的基礎上新增了poll機制來優化程式

我們知道,應用程式中的open、read、write函式會呼叫核心裡的sys_open、sys_read、sys_write函式,而核心裡的這些函式又會對應到驅動程式裡的.open、.read、.write函式。我們的poll機制也不例外,使用者空間裡可以採用poll函式或者select函式,他們都會呼叫到核心空間的sys_poll函式,而sys_poll函式最後又會對應到驅動程式裡的.poll函式。下面我們從sys_poll開始來分析poll機制,我們只列出分析的框架:

kernel: sys_poll(struct pollfd __user *ufds, unsigned int nfds, long timeout_msecs)

timeout_jiffies = msecs_to_jiffies(timeout_msecs);   

//配置超時時間

do_sys_poll(ufds, nfds, &timeout_jiffies);

poll_initwait(&table);

//初始化等待佇列

init_poll_funcptr(&pwq->pt, __pollwait);

pt->qproc = qproc;    

//table->pt->qproc=

__pollwait;,見注釋1-2

do_poll(nfds, head, &table, timeout);

for (;;) }

/*若count不為0或者超時或者有事件發生則會跳出死迴圈*/

if (count || !*timeout || signal_pending(current))

break;

/*若count為0且未超時且無事件發生則會休眠__timeout時間*/

schedule_timeout(__timeout);

} 注釋1-1:

do_pollfd(pfd, pt)

mask = file->f_op->poll(file, pwait);

//貌似呼叫了驅動程式中的poll函式,若poll函式返回值不為0則會使count++

注釋1-2:

__pollwait函式中有這麼一句:

entry->wait_address = wait_address;

用於將當前程序掛到等待佇列中,

table->pt->

qproc=

__pollwait就說明

table->pt->

qproc函式可以將

當前程序掛到等待佇列中。

以上是從sys_poll出發分析出的框架,下面我們可以從乙個驅動中poll函式的例子出發在來分析一下,希望可以把跟上面相銜接上,先來看**:

static unsigned forth_drv_poll(struct file *file, poll_table *wait)

分析如下:

poll_wait(file, &button_waitq, wait)原型如下:

static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)

注釋2-1:

在注釋1-2中,我們曾經分析出了

qproc函式的作用是

將 當前程序掛到等待佇列中

,於是我們就知道了

poll_wait函式是將當前程序掛到等待佇列

button_waitq中

。要注意現在只是加入等待佇列,但是並沒有出現休眠。

ok!這樣我們就聯絡起來了。總結一下下:

從sys_poll出發,首先定義了

qproc函式,然後呼叫驅動程式裡的poll函式,首先將等待佇列新增到等待佇列列表中,然後判斷是否有按鍵按下,如果有按鍵按下,則返回為非0。這時就會跳出死迴圈,如果沒有按鍵按下的話返回為0,這時如果沒有其他事件發生,就會進入休眠,休眠一段時間後,會重新迴圈,但此時經出現超時,所以會跳出迴圈,返回應用程式。

下面我們來看一下完整的驅動程式**:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define device_name "keys"

volatile unsigned long *gpfcon=null;

volatile unsigned long *gpfdat=null;

volatile unsigned long *gpgcon=null;

volatile unsigned long *gpgdat=null;

static struct class *keys_class;

static struct class_device

*keys_class_devs;

struct pin_desc;

static unsigned char key_val;

struct pin_desc pins_desc[4] = , ,

, ,};

static declare_wait_queue_head(button_waitq);

static volatile int ev_press = 0;

static irqreturn_t buttons_irq(int irq, void *dev_id) 

else

ev_press=1;

wake_up_interruptible(&button_waitq); /* ?????????????? */

return irq_retval(irq_handled); }

static int s3c24xx_keys_open(struct inode *inode, struct file *file)

static int s3c24xx_keys_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

int s3c24xx_keys_close(struct inode *inode, struct file *file)

static unsigned s3c24xx_keys_poll(struct file *file, poll_table *wait)

static struct file_operations s3c24xx_keys_fops = ;

int major;

static int __init s3c24xx_keys_init(void)

static void __exit s3c24xx_keys_exit(void)

module_init(s3c24xx_keys_init);

module_exit(s3c24xx_keys_exit);

module_license("gpl");

測試程式:

#include

#include

#include

#include

#include

int main(int argc, char **argv)

fds[0].fd     = fd;

fds[0].events = pollin;

while (1)

else

}

return 0;

}本程式實現的功能和上一節相同,不同的是,上一節我們是在read函式中,根據按鍵是否被按下判斷是否進入休眠。而本節中我們引入了poll機制,poll函式自動完成將當前程序加入等待佇列,這是還不會進入休眠,然後會判斷是否有按鍵按下,如果有按鍵按下,這是返回值為非0,不會進入休眠,如果沒有按鍵按下,則返回值為0,就會進入休眠。在休眠過程中,如果發生中斷的話,就會喚醒程序,返回應用程式繼續執行。

linux裝置驅動程式 字元裝置驅動程式

先留個 有一起學習驅動程式的加qq295699450 字元裝置驅動 這篇比較惱火。載入成功,但是讀不出來資料,有知道怎麼回事的,留個言,一起討論下 資料結構 struct scull mem struct scull dev dev 整個驅動程式 如下 include include include...

Linux裝置驅動程式 字元裝置驅動程式

1.檢視主裝置號,次裝置號 進入 dev目錄執行ls l,第四,五列分別為主次裝置號,10,180,1,5,這些是主裝置號,而60,63這些就是次裝置號 130 shell android dev ls l crw rw r system radio 10,60 1969 12 31 21 00 a...

裝置驅動 字元裝置驅動程式

linux下的應用程式在訪問字元裝置時,一般都是通過裝置檔案訪問的。裝置檔案一般都存放在 dev目錄下。字元裝置檔案的第乙個標誌是c,如下所示 總結 每乙個檔案代表乙個裝置,在時間前面有兩個用逗號隔開的數字,第乙個數字是主裝置號,第二個數字是次裝置號。一般認為乙個主裝置號對應乙個驅動程式,這裡列出的...