本節裡我們在按鍵中斷機制的基礎上新增了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,如下所示 總結 每乙個檔案代表乙個裝置,在時間前面有兩個用逗號隔開的數字,第乙個數字是主裝置號,第二個數字是次裝置號。一般認為乙個主裝置號對應乙個驅動程式,這裡列出的...