競爭的關鍵驅動的非同步通知

來源:互聯網
上載者:User

標籤:

       轉載請註明出處:http://blog.csdn.net/ruoyunliufeng/article/details/24326603

       說起非同步通知,簡單點的理解就是:曾經都是應用程式主動看按鍵是否按下云云的。

。

。

這回應用程式架子大了。說老子才不去呢。

把任務給了驅動。

然後驅動發現按鍵按下。屁顛屁顛的去通知應用程式。


一.驅動代碼

      假設你看了前幾篇文章。這個代碼對你來說是很easy的,所修改的東西很的少。

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/irq.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>#include <linux/poll.h>static struct class *fifthdrv_class;static struct class_device*fifthdrv_class_dev;//volatile unsigned long *gpfcon;//volatile unsigned long *gpfdat;static DECLARE_WAIT_QUEUE_HEAD(button_waitq);/* 中斷事件標誌, 中斷服務程式將它置1。fifth_drv_read將它清0 */static volatile int ev_press = 0;static struct fasync_struct *button_async;  //定義一個結構struct pin_desc{                  //定義結構體unsigned int pin;unsigned int key_val;};/* 索引值: 按下時, 0x01, 0x02, 0x03, 0x04 *//* 索引值: 鬆開時, 0x81, 0x82, 0x83, 0x84 */static unsigned char key_val;/* * K1,K2,K3,K4相應GPG0,GPG3,GPG5,GPG6 */struct pin_desc pins_desc[4] = {     //定義一個結構體數組{S3C2410_GPG0, 0x01},{S3C2410_GPG3, 0x02},{S3C2410_GPG5, 0x03},{S3C2410_GPG6, 0x04},};/*  * 確定按索引值  */static irqreturn_t buttons_irq(int irq, void *dev_id)          //參數中斷號,和ID{struct pin_desc * pindesc = (struct pin_desc *)dev_id;    //?

定義一個結構體指標使他的初值為IDunsigned int pinval;pinval = s3c2410_gpio_getpin(pindesc->pin); //系統函數獨處引腳值(GPF0)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);}static int fifth_drv_open(struct inode *inode, struct file *file){/* GPG0。GPG3,GPG5。GPG6為中斷引腳: EINT8,EINT11,EINT13,EINT14 */request_irq(IRQ_EINT8, buttons_irq, IRQT_BOTHEDGE, "K1", &pins_desc[0]);request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "K2", &pins_desc[1]);request_irq(IRQ_EINT13, buttons_irq, IRQT_BOTHEDGE, "K3", &pins_desc[2]);request_irq(IRQ_EINT14, buttons_irq, IRQT_BOTHEDGE, "K4", &pins_desc[3]);return 0;}ssize_t fifth_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;}int fifth_drv_close(struct inode *inode, struct file *file) //出鏈,禁止中斷{free_irq(IRQ_EINT8, &pins_desc[0]);free_irq(IRQ_EINT11, &pins_desc[1]);free_irq(IRQ_EINT13, &pins_desc[2]);free_irq(IRQ_EINT14, &pins_desc[3]);return 0;}static unsigned 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;}static int fifth_drv_fasync (int fd, struct file *filp, int on) {printk("driver: fifth_drv_fasync\n"); //為了說明次函數被調用添加一條列印語句return fasync_helper (fd, filp, on, &button_async); //初始化定義的結構體}static struct 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,};int major;static int 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;return 0;}static void fifth_drv_exit(void){unregister_chrdev(major, "fifth_drv");class_device_unregister(fifthdrv_class_dev);class_destroy(fifthdrv_class);//iounmap(gpfcon);return 0;}module_init(fifth_drv_init);module_exit(fifth_drv_exit);MODULE_LICENSE("GPL");




二.應用程式代碼

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <poll.h>#include <signal.h>#include <sys/types.h>#include <unistd.h>#include <fcntl.h>/* fifthdrvtest   */int fd;void my_signal_fun(int signum)    //訊號處理函數{unsigned char key_val;read(fd, &key_val, 1);       //讀取按索引值printf("key_val: 0x%x\n", key_val);  //列印}int main(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‘t open!\n");}fcntl(fd, F_SETOWN, getpid());      // 告訴核心,發給誰(通過PID)Oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, Oflags | FASYNC);  // 改變fasync標記,終於會調用到驅動的faync > fasync_helper:初始化/釋放fasync_structwhile (1){sleep(1000);}return 0;}




三.分析

           1.應用程式

        首先來看看應用程式都幹了些什麼。應用程式首先注冊了訊號處理函數(函數的處理主要寫在這裡)。然後開啟驅動。主函數中while(1)中是個迴圈,一直睡眠。

其中斷髮生時候,驅動會把訊號發給應用程式。應用程式在訊號處理函數進行處理。fcntl(fd, F_SETOWN, getpid());

                                Oflags = fcntl(fd, F_GETFL);
                                fcntl(fd, F_SETFL, Oflags | FASYNC);
這三段代碼是應用程式實現非同步通知的機制所在。

使用者程式必須運行 2 個步驟來使能來自輸入檔案的非同步通知. 首先, 它們指定一個進程作為檔案的擁有者. 當一個進程使用 fcntl 系統調用發出 F_SETOWN 命令, 這個擁有者進程的 ID 被儲存在 filp->f_owner 給以後使用. 這一步對核心知道通知誰是必要的. 為了真正使能非同步通知, 使用者程式必須設定 FASYNC 標誌在裝置中, 通過 F_SETFL fcntl 命令.

在這 2 個調用已被運行後, 輸入檔案可請求遞交一個 SIGIO 訊號, 不管何時新資料到達. 訊號被發送給儲存於 filp->f_owner 中的進程(或者進程組, 假設值為負值).


(說的有點可能難以理解。沒關係最後會用一張圖給小夥伴們說明當中的道理)


           2.驅動程式

1. 當發出 F_SETOWN, 什麼都沒發生, 除了一個值被賦值給 filp->f_owner.(核心完畢的)

2.當 F_SETFL 被運行來開啟 FASYNC, 驅動的 fasync 方法被調用.

static int fifth_drv_fasync (int fd, struct file *filp, int on)   {printk("driver: fifth_drv_fasync\n");             //為了說明次函數被調用添加一條列印語句return fasync_helper (fd, filp, on, &button_async); //初始化定義的結構體}
3. 當資料到達, 全部的注冊非同步通知的進程必須被發出一個 SIGIO 訊號.

kill_fasync (&button_async, SIGIO, POLL_IN);  
到這裡應用程式就接收到訊號了,運行對應的操作了。


       

           3.圖片

你發現怎麼我按下一次出現了了好幾個0x1啊。賣個關子,以下幾篇會有講訴。


watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcnVveXVubGl1ZmVuZw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >


著作權聲明:本文部落格原創文章,部落格,未經同意,不得轉載。

競爭的關鍵驅動的非同步通知

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.