此驅動程式之前的按鍵驅動程式(中斷方式)上加以優化。用到非同步通知。對於核心來講,既然使用者想得到的是按鍵後的狀態,那麼自然不必時時都要read狀態。當它檢測到中斷發生變主動通知使用者,使用者再來讀。這樣,使用者空間、核心就可以著手幹點其它的事情,而不必忙等按鍵按下或釋放。那麼就先從應用程式上面看。
怎麼設定相關聯到「非同步通知」呢?
flag = fcntl(fd, f_getfl);
fcntl(fd, f_setfl, flag|fasync);
這樣的兩句就可以將檔案描述符fd與非同步通知關聯,到時候將會接到相關通知。
怎麼知道通知道本程式呢?
fcntl(fd, f_setown, getpid());
將其與程序號關聯,這樣核心就知道要將通知發往本程序。
得到通知後該怎麼做呢?
sighandler_t signal(int signum, sighandler_t handler);
後面的handler是接到訊號後的處理函式,而對於一般的io操作,signum通常為sigio,這點在核心驅動中要保持一致。handler的定義為
typedef void (*sighandler_t)(int); 在這個函式體內就可以去read資料了。
詳細的驅動程式為:
[plain]view plain
copy
print?
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fifthdev mkdev(250, 0)
struct cdev fifthdrv_cdev;
static struct class *fifthdrv_class;
struct button ;
//static volatile int pressed = 0;
static unsigned char key_val;
struct fasync_struct *button_async;
//declare_wait_queue_head(button_wqh);
/* 六個按鍵的相關定義整合到結構體 */
static struct button buttons[6] = ,
, ,
, ,
, };
/* 中斷處理函式 */
static irqreturn_t fifthdrv_intr(int irq, void *data)
else
//pressed = 1; //此處改變按下標誌,以使佇列不繼續睡眠
//wake_up_interruptible(&button_wqh);
kill_fasync(&button_async, sigio, poll_in);
return irq_retval(irq_handled);
} static int fifthdrv_open(struct inode * inode, struct file * file)
return 0;
} static ssize_t fifthdrv_read(struct file *file, char __user *user, size_t size,loff_t*o)
/* 使用非同步通知,此處不必休眠 */
//wait_event_interruptible(button_wqh, pressed);
copy_to_user(user, &key_val, sz);
/* 重新清除按下標誌 */
//pressed = 0;
return sz;
} static int fifthdrv_close(struct inode *inode, struct file *file)
return 0;
} /*
static unsigned int fifthdrv_poll(struct file *file, poll_table *wait)
return res;
} */
static int fifthdrv_fasync(int fd, struct file *filp, int on)
static struct file_operations fifthdrv_ops = ;
static int fifthdrv_init(void)
fifthdrv_class = class_create(this_module, "fifthdrv_class");
if (is_err(fifthdrv_class))
device_create(fifthdrv_class, null, devt, null, "buttons");
cdev_init(&fifthdrv_cdev, &fifthdrv_ops);
ret = cdev_add(&fifthdrv_cdev, devt, 1);
if (ret
goto fail_cdev;
return 0;
fail_cdev:
class_unregister(fifthdrv_class);
device_destroy(fifthdrv_class, devt);
cdev_del(&fifthdrv_cdev);
fail:
unregister_chrdev_region(devt, 1);
return 0;
} static void fifthdrv_exit(void)
module_init(fifthdrv_init);
module_exit(fifthdrv_exit);
module_license("gpl");
應用程式為:
#include
#include
#include
#include
#include
int fd;
void signal_f(int signum)
int main(int argc, char *ar**)
signal(sigio, signal_f);
fcntl(fd, f_setown, getpid());
flag = fcntl(fd, f_getfl);
fcntl(fd, f_setfl, flag|fasync);
while (1)
return 0;}
執行狀態:
本文**:
字元裝置驅動程式 非同步通知
1.各種讀取按鍵值的方式比較 查詢 耗cpu資源 中斷 在應用程式中的read函式一直會休眠,直到有中斷發生。poll 在一段時間內跟中斷相同,但是超時之後read函式會返回。三種共同點 應用程式主動去讀取按鍵的狀態。2.驅動程式主動去提醒應用的方式 非同步通知 實現方式 signal 舉例 kil...
基於非同步通知機制的按鍵驅動
按下按鍵是驅動程式通知應用程式 應用程式裡面要註冊訊號處理函式 驅動程式給應用程式發訊號 發給誰,這就要應用程式告訴驅動pid了 怎麼發,是驅動裡面呼叫kill fasync 為了使裝置支援非同步通知機制,驅動程式涉及以下3項工作 1.支援f setown命令,能在這個控制命令處理中設定filp f...
中斷 按鍵中斷驅動程式
中斷處理 1 外設的處理速度一般慢於 cpu。2 cpu不能一直等待外部事件,所以裝置必須有一種方法來通知 cpu它的工作進度,這個方法就是中斷,外設與 cpu資訊互動的機制,提高 cpu利用率。處理之外還有查詢,但是查詢會一直占有 cpu資源,導致 cpu低利用率,好處是實現簡單。linux系統中...