非同步通知筆記
應用程式需要完成如下三個步驟: 1
)signal(sigio, sig_handler);
呼叫signal函式,讓指定的訊號sigio與處理函式sig_handler對應。2)
fcntl(fd, f_set_owner, getpid());
指定乙個程序作為檔案的「屬主(filp->owner)」,這樣核心才知道訊號要發給哪個程序。3)
f_flags = fcntl(fd, f_getfl);
fcntl(fd,f_setfl, f_flags | fasync);
在裝置檔案中新增fasync標誌,驅動中就會呼叫將要實現的test_fasync函式。
三個步驟執行後,一旦有訊號產生,相應的程序就會收到。
核心需要完成下面四個步驟:
1)定義結構體fasync_struct。
static struct fasync_struct *button_async;
2)實現t fifth_drv_fasync,把函式fasync_helper將fd,filp和定義的結構體傳給核心。
static int fifth_drv_fasync (int fd, struct file *filp, int on)
3)當裝置可寫時,呼叫函式kill_fasync傳送訊號sigio給核心。
kill_fasync(&button_async, sigio, poll_in);
4
)完成ops
structfile_operations test_fops = ,,,
,* 確定按鍵值
staticirqreturn_t buttons_irq(int irq, void *dev_id)
struct pin_desc * pindesc = (structpin_desc *)dev_id;
unsigned int pinval;
pinval =s3c2410_gpio_getpin(pindesc->pin);
if (pinval)
/* 鬆開 */
key_val = 0x80 |pindesc->key_val;
else
/* 按下 */
key_val =pindesc->key_val;
ev_press = 1; /* 表示中斷發生了 */
wake_up_interruptible(&button_waitq); /* 喚醒休眠的程序 */
kill_fasync (&button_async, sigio,poll_in);
return irq_retval(irq_handled);
staticint fifth_drv_open(struct inode *inode, struct file *file)
/* 配置gpf0,2為輸入引腳 */
/* 配置gpg3,11為輸入引腳 */
request_irq(irq_eint0, buttons_irq, irqt_bothedge, "s2",&pins_desc[0]);
request_irq(irq_eint2, buttons_irq, irqt_bothedge, "s3",&pins_desc[1]);
request_irq(irq_eint11, buttons_irq,irqt_bothedge, "s4", &pins_desc[2]);
request_irq(irq_eint19, buttons_irq,irqt_bothedge, "s5", &pins_desc[3]);
return 0;
ssize_tfifth_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
if (size != 1)
return -einval;
/* 如果沒有按鍵動作, 休眠 */
wait_event_interruptible(button_waitq,ev_press);
/* 如果有按鍵動作, 返回鍵值 */
copy_to_user(buf, &key_val, 1);
ev_press = 0;
return 1;
intfifth_drv_close(struct inode *inode, struct file *file)
free_irq(irq_eint0, &pins_desc[0]);
free_irq(irq_eint2, &pins_desc[1]);
free_irq(irq_eint11,&pins_desc[2]);
free_irq(irq_eint19,&pins_desc[3]);
return 0;
staticunsigned fifth_drv_poll(struct file *file, poll_table *wait)
unsigned int mask = 0;
poll_wait(file, &button_waitq,wait); // 不會立即休眠
if (ev_press)
mask |= pollin | pollrdnorm;
return mask;
staticint fifth_drv_fasync (int fd, struct file *filp, int on)
printk("driver:fifth_drv_fasync\n");
return fasync_helper (fd, filp, on,&button_async);
staticstruct file_operations sencod_drv_fops = {
.owner = this_module, /* 這是乙個巨集,推向編譯模組時自動建立的__this_module變數 */
.open = fifth_drv_open,
.read = fifth_drv_read,
.release = fifth_drv_close,
.poll = fifth_drv_poll,
.fasync = fifth_drv_fasync,
intmajor;
staticint fifth_drv_init(void)
major = register_chrdev(0,"fifth_drv", &sencod_drv_fops);
fifthdrv_class =class_create(this_module, "fifth_drv");
fifthdrv_class_dev =class_device_create(fifthdrv_class, null, mkdev(major, 0), null,"buttons"); /* /dev/buttons */
gpfcon = (volatile unsigned long*)ioremap(0x56000050, 16);
gpfdat = gpfcon + 1;
gpgcon = (volatile unsigned long*)ioremap(0x56000060, 16);
gpgdat = gpgcon + 1;
return 0;
staticvoid fifth_drv_exit(void)
unregister_chrdev(major,"fifth_drv");
class_device_unregister(fifthdrv_class_dev);
class_destroy(fifthdrv_class);
iounmap(gpfcon);
iounmap(gpgcon);
return 0;
module_init(fifth_drv_init);
module_exit(fifth_drv_exit);
module_license("gpl");
測試應用程式
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*fifthdrvtest
intfd;
voidmy_signal_fun(int signum)
unsigned char key_val;
read(fd, &key_val, 1);
printf("key_val: 0x%x\n",key_val);
intmain(int argc, char **argv)
unsigned char key_val;
int ret;
int oflags;
signal(sigio, my_signal_fun);
fd = open("/dev/buttons",o_rdwr);
if (fd < 0)
printf("can'topen!\n");
fcntl(fd, f_setown, getpid());
oflags = fcntl(fd, f_getfl);
fcntl(fd, f_setfl, oflags | fasync);
while (1)
sleep(1000);
return 0;
Linux GPIO中斷非同步通知
fasync機制是非同步通知機制,當驅動程式向應用程式傳送訊號量,觸發應用程式的訊號處理函式,以達到類似中斷的效果 驅動程式中 1 在檔案專屬的fasync函式中,呼叫了fasync helper,將屬主資訊通知給核心 2 當發生按鍵中斷,進入按鍵中斷服務程式,讀取鍵值,呼叫kill fasync,...
Linux非同步通知 fasync
要弄明白這個問題,我們得從最基本的原理開始。我們知道,驅動程式執行在核心空間中,應用程式執行在使用者空間中,兩者是不能直接通訊的。但在實際應用中,在裝置已經準備好的時候,我們希望通知使用者程式裝置已經ok,使用者程式可以讀取了,這樣應用程式就不需要一直查詢該裝置的狀態,從而節約資源,這就是非同步通知...
Linux非同步通知fasync
實現非同步通知,核心需要知道幾個東西 哪個檔案 filp 什麼訊號 sigiio 發給哪個程序 pid 收到訊號後做什麼 sig handler 這些都由前兩個步驟完成了。在這裡,同樣需要把乙個結構體 struct fasync struct 新增到核心的非同步佇列頭 名字是我自己取的 中。這個結構...