Linux中斷非同步通知筆記

2021-06-25 08:17:27 字數 4857 閱讀 2310

非同步通知筆記

應用程式需要完成如下三個步驟: 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 新增到核心的非同步佇列頭 名字是我自己取的 中。這個結構...