娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

Linux驅(qū)動(dòng)之異步通知的應(yīng)用

發(fā)布者:yuehui最新更新時(shí)間:2024-08-20 來(lái)源: cnblogs關(guān)鍵字:Linux驅(qū)動(dòng)  異步通知 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

前面的按鍵驅(qū)動(dòng)方式都是應(yīng)用程序通過(guò)主動(dòng)查詢的方式獲得按鍵值的:


1、查詢方式


2、中斷方式


3、poll機(jī)制


下面介紹第四種按鍵驅(qū)動(dòng)的方式


4、異步通知:它可以做到應(yīng)用程序不用隨時(shí)去查詢按鍵的狀態(tài),而等待有按鍵被按下后,驅(qū)動(dòng)程序主動(dòng)發(fā)消息給應(yīng)用程序,應(yīng)用程序再去處理。


比如說(shuō):kill -9 pid即是一種發(fā)信號(hào)的過(guò)程:其中9就是信號(hào)值,pid就是被發(fā)送的進(jìn)程的進(jìn)程號(hào)


a、一個(gè)簡(jiǎn)單的異步通知的例子


b、編寫測(cè)試程序?qū)崿F(xiàn)異步通知


c、更改按鍵驅(qū)動(dòng)實(shí)現(xiàn)異步通知


1、一個(gè)簡(jiǎn)單的異步通知的例子


直接看到程序源碼,可以看到這個(gè)程序在主程序里面什么事情也沒(méi)有做,一直處于睡眠狀態(tài)。


#include



void my_signal_test(int signum)

{

    static int cnt = 0;

    printf('signal = %d,%d timesn',signum,++cnt);

}


int main(int argc,char **argv)

{

    signal(SIGUSR1, my_signal_test);//建立一個(gè)信號(hào)函數(shù),接收的信號(hào)是SIGUSR1表示用戶可用的信號(hào)值


    while(1)

    {

        sleep(1000);

    }

    return 0;

}


首先這個(gè)程序調(diào)用了signal這個(gè)C庫(kù)中的函數(shù),在linux下查詢它的用法輸入man 2 signal


#include //需要包含的頭文件


typedef void (*sighandler_t)(int);//信號(hào)函數(shù)原型,它的參數(shù)是信號(hào)值


sighandler_t signal(int signum, sighandler_t handler);//函數(shù),其中signum代表發(fā)送的信號(hào)值,handler表示信號(hào)函數(shù)

編譯這個(gè)程序,然后在命令行輸入kill -USR1 2333,my_signal函數(shù)被運(yùn)行。


2、更改測(cè)試程序?qū)崿F(xiàn)異步通知


直接看代碼,從代碼可以看出,實(shí)現(xiàn)異步通知在應(yīng)用層需要如下幾步:


1、利用signal(SIGIO, fifth_testsignal)函數(shù)注冊(cè)一個(gè)信號(hào),信號(hào)處理的函數(shù)為fifth_testsignal。SISGIO說(shuō)明是IO信號(hào)量,因?yàn)榘存I驅(qū)動(dòng)屬于IO型的。


2、利用fcntl(fd, F_SETOWN, getpid())函數(shù)將本應(yīng)用程序的進(jìn)程號(hào)告訴給內(nèi)核,最終使得驅(qū)動(dòng)程序可以成功發(fā)送信號(hào)給應(yīng)用程序。


3、利用fcntl(fd, F_SETFL, oflags | FASYNC)函數(shù)改變fasync標(biāo)記,最終會(huì)調(diào)用到驅(qū)動(dòng)的faync > fasync_helper。


4、signal、與fcntl的系統(tǒng)調(diào)用過(guò)程比較復(fù)雜,后面再去分析。這里只能記住是怎么使用它們來(lái)是實(shí)現(xiàn)異步通知的功能。


#include

#include

#include

#include

#include

#include


static int fd;


static void fifth_testsignal(int signum)

{

    unsigned char key_val;

    

    printf('signal = %dn',signum);


    read(fd, &key_val, 1);//讀取按鍵數(shù)據(jù),只有收到按鍵數(shù)據(jù)驅(qū)動(dòng)層才會(huì)發(fā)送消息給應(yīng)用層。

         printf('signumkey_val: 0x%xnn',key_val);

}


/*

  *usage ./buttonstest

  */

int main(int argc, char **argv)

{

    char* filename='dev/buttons';

   int oflags;


    

    fd = open(filename, O_RDWR);//打開dev/firstdrv設(shè)備文件

    if (fd < 0)//小于0說(shuō)明沒(méi)有成功

    {

        printf('error, can't open %sn', filename);

        return 0;

    }

    

    if(argc !=1)

    {

        printf('Usage : %s ',argv[0]);

     return 0;

    }

    signal(SIGIO, fifth_testsignal);//注冊(cè)一個(gè)信號(hào),函數(shù)為fifth_testsignal

    

    fcntl(fd, F_SETOWN, getpid());  // 告訴內(nèi)核,發(fā)給誰(shuí)

    

    oflags = fcntl(fd, F_GETFL); //取得當(dāng)前的狀態(tài)

    

    fcntl(fd, F_SETFL, oflags | FASYNC);  // 改變fasync標(biāo)記,最終會(huì)調(diào)用到驅(qū)動(dòng)的faync > fasync_helper:初始化/釋放fasync_struct

    

  while(1)

  {

    sleep(1000);

  }

    

   return 0;

}


3、更改按鍵驅(qū)動(dòng)實(shí)現(xiàn)異步通知功能


與原先的按鍵驅(qū)動(dòng)程序相比:


1、定義fasync_struct結(jié)構(gòu)


struct fasync_struct *fifth_fasync;//定義fasync_struct結(jié)構(gòu)

2、在fifth_drv_ops 結(jié)構(gòu)體中增加fifth_drv_fasync異步通知處理函數(shù)


static struct file_operations fifth_drv_ops = 

{

    .owner   = THIS_MODULE,

    .open    =  fifth_drv_open,

    .read     = fifth_drv_read,

    .release = fifth_drv_close,

    .poll      =  fifth_drv_poll,

    .fasync   = fifth_drv_fasync,//增加異步通知處理的函數(shù)

    

};


3、編寫fifth_drv_fasync異步通知處理函數(shù),這個(gè)函數(shù)會(huì)在C庫(kù)函數(shù)fcntl設(shè)置FASYNC時(shí)被調(diào)用


static int fifth_drv_fasync(int fd, struct file * file, int on)

{

    int err;

    printk('fansync_helpern');

    err = fasync_helper(fd, file, on, &fifth_fasync);//利用fasync_helper初始化fifth_fasync

    if (err < 0)

        return err;

    return 0;

}


下面是完整的代碼


#include

#include

#include

#include

#include         //含有iomap函數(shù)iounmap函數(shù)

#include //含有copy_from_user函數(shù)

#include //含有類相關(guān)的處理函數(shù)

#include //含有S3C2410_GPF0等相關(guān)的

#include     //含有IRQ_HANDLEDIRQ_TYPE_EDGE_RISING

#include    //含有IRQT_BOTHEDGE觸發(fā)類型

#include //含有request_irq、free_irq函數(shù)

#include

//#include




static struct class *fifth_drv_class;//類

static struct class_device *fifth_drv_class_dev;//類下面的設(shè)備

static int fifthmajor;


static unsigned long *gpfcon = NULL;

static unsigned long *gpfdat = NULL;

static unsigned long *gpgcon = NULL;

static unsigned long *gpgdat = NULL;


struct fasync_struct *fifth_fasync;//定義fasync_struct結(jié)構(gòu)

    

static unsigned int key_val;


struct pin_desc 

{

    unsigned int pin;

    unsigned int key_val;

};


static struct pin_desc  pins_desc[4] = 

{

    {S3C2410_GPF0,0x01},

    {S3C2410_GPF2,0x02},

    {S3C2410_GPG3,0x03},

    {S3C2410_GPG11,0x04}

};



unsigned int ev_press;

DECLARE_WAIT_QUEUE_HEAD(button_waitq);//注冊(cè)一個(gè)等待隊(duì)列button_waitq


 

/*

  *0x01、0x02、0x03、0x04表示按鍵被按下

  */

  

/*

  *0x81、0x82、0x83、0x84表示按鍵被松開

  */


/*

  *利用dev_id的值為pins_desc來(lái)判斷是哪一個(gè)按鍵被按下或松開

  */

static irqreturn_t buttons_irq(int irq, void *dev_id)

{

    unsigned int pin_val;

    struct pin_desc * pin_desc = (struct pin_desc *)dev_id;//取得哪個(gè)按鍵被按下的狀態(tài)

    

    pin_val = s3c2410_gpio_getpin(pin_desc->pin);

    

    if(pin_val) //按鍵松開

        key_val = 0x80 | pin_desc->key_val;

    else

        key_val = pin_desc->key_val;



    wake_up_interruptible(&button_waitq);   /* 喚醒休眠的進(jìn)程 */

    ev_press = 1;    

    

    kill_fasync(&fifth_fasync, SIGIO, POLL_IN);//發(fā)生信號(hào)給進(jìn)程

    

    return IRQ_HANDLED;

}




static int fifth_drv_open (struct inode * inode, struct file * file)

{

    int ret;

    ret = request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, 's1', (void * )&pins_desc[0]);

    if(ret)

    {

        printk('open failed 1n');

        return -1;

    }

    ret = request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, 's2', (void * )& pins_desc[1]);

    if(ret)

    {

        printk('open failed 2n');

        return -1;

    }

    ret = request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, 's3', (void * )&pins_desc[2]);

    if(ret)

    {

        printk('open failed 3n');

        return -1;

    }

    ret = request_irq(IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, 's4', (void * )&pins_desc[3]);

    if(ret)

    {

        printk('open failed 4n');

        return -1;

    }

    

    return 0;

}



static int fifth_drv_close(struct inode * inode, struct file * file)

{

    free_irq(IRQ_EINT0 ,(void * )&pins_desc[0]);


     free_irq(IRQ_EINT2 ,(void * )& pins_desc[1]);


    free_irq(IRQ_EINT11 ,(void * )&pins_desc[2]);


    free_irq(IRQ_EINT19 ,(void * )&pins_desc[3]);


    return 0;

}


static ssize_t fifth_drv_read(struct file * file, char __user * userbuf, size_t count, loff_t * off)

{

    int ret;


    if(count != 1)

    {

        printk('read errorn');

        return -1;

    }


//    wait_event_interruptible(button_waitq, ev_press);//將當(dāng)前進(jìn)程放入等待隊(duì)列button_waitq中

    

    ret = copy_to_user(userbuf, &key_val, 1);

    ev_press = 0;//按鍵已經(jīng)處理可以繼續(xù)睡眠

    

    if(ret)

    {

        printk('copy errorn');

        return -1;

    }

    

    return 1;

}


static unsigned int fifth_drv_poll(struct file *file, poll_table *wait)

{

    unsigned int ret = 0;

    poll_wait(file, &button_waitq, wait);//將當(dāng)前進(jìn)程放到button_waitq列表


    if(ev_press)

        ret |=POLLIN;//說(shuō)明有數(shù)據(jù)被取到了


    return ret;

}




static int fifth_drv_fasync(int fd, struct file * file, int on)

{

    int err;

    printk('fansync_helpern');

    err = fasync_helper(fd, file, on, &fifth_fasync);//利用fasync_helper初始化fifth_fasync

    if (err < 0)

        return err;

    return 0;

}



static struct file_operations fifth_drv_ops = 

{

    .owner   = THIS_MODULE,

    .open    =  fifth_drv_open,

    .read     = fifth_drv_read,

    .release = fifth_drv_close,

    .poll      =  fifth_drv_poll,

    .fasync   = fifth_drv_fasync,//增加異步通知處理的函數(shù)

    

};


static int fifth_drv_init(void)

{

    fifthmajor = register_chrdev(0, 'buttons', &fifth_drv_ops);//注冊(cè)驅(qū)動(dòng)程序


    if(fifthmajor < 0)

        printk('failes 1 buttons_drv registern');

    

    fifth_drv_class = class_create(THIS_MODULE, 'buttons');//創(chuàng)建類

    if(fifth_drv_class < 0)

        printk('failes 2 buttons_drv registern');

    fifth_drv_class_dev = class_device_create(fifth_drv_class, NULL, MKDEV(fifthmajor,0), NULL,'buttons');//創(chuàng)建設(shè)備節(jié)點(diǎn)

    if(fifth_drv_class_dev < 0)

        printk('failes 3 buttons_drv registern');


    

    gpfcon = ioremap(0x56000050, 16);//重映射

    gpfdat = gpfcon + 1;

    gpgcon = ioremap(0x56000060, 16);//重映射

    gpgdat = gpgcon + 1;


    printk('register buttons_drvn');

    return 0;

[1] [2]
關(guān)鍵字:Linux驅(qū)動(dòng)  異步通知 引用地址:Linux驅(qū)動(dòng)之異步通知的應(yīng)用

上一篇:Linux驅(qū)動(dòng)之異步OR同步,阻塞OR非阻塞概念介紹
下一篇:Linux驅(qū)動(dòng)之poll機(jī)制的理解與簡(jiǎn)單使用

推薦閱讀最新更新時(shí)間:2025-06-07 23:41

Linux-2.6.39在Tiny6410上的移植 - 外設(shè)驅(qū)動(dòng)移植
Linux內(nèi)核版本號(hào):linux 2.6.39 交叉編譯工具:arm-linux-gcc 4.5.1 Linux內(nèi)核下載:www.kernel.org 開發(fā)板:友善之臂Tiny6410 LCD:友善之臂S70 一、移植LED驅(qū)動(dòng) 打開arch/arm/mach-s3c64xx/mach-mini6410.c添加下列代碼: 1 static struct gpio_led tiny6410_gpio_led = { 2 = { 3 .name = led1 , //設(shè)備名 4 .gpio = S3C64XX_GPK(4), //GPK4 5 .act
[單片機(jī)]
ARM Linux字符設(shè)備驅(qū)動(dòng)程序
1、主設(shè)備號(hào)和次設(shè)備號(hào)(二者一起為設(shè)備號(hào)): 一個(gè)字符設(shè)備或塊設(shè)備都有一個(gè)主設(shè)備號(hào)和一個(gè)次設(shè)備號(hào)。主設(shè)備號(hào)用來(lái)標(biāo)識(shí)與設(shè)備文件相連的驅(qū)動(dòng)程序,用來(lái)反 映設(shè)備類型。次設(shè)備號(hào)被驅(qū)動(dòng)程序用來(lái)辨別操作的是哪個(gè)設(shè)備,用來(lái)區(qū)分同類型的設(shè)備。 linux內(nèi)核中,設(shè)備號(hào)用dev_t來(lái)描述,2.6.28中定義如下: typedef u_long dev_t; 在32位機(jī)中是4個(gè)字節(jié),高12位表示主設(shè)備號(hào),低12位表示次設(shè)備號(hào)。 可以使用下列宏從dev_t中獲得主次設(shè)備號(hào):                    也可以使用下列宏通過(guò)主次設(shè)備號(hào)生成dev_t: MAJOR(dev_t dev); MKDEV(int major,int
[單片機(jī)]
ARM <font color='red'>Linux</font>字符設(shè)備<font color='red'>驅(qū)動(dòng)</font>程序
linux-2.6.32在mini2440開發(fā)板上移植 移植I2C-EEPROM 驅(qū)動(dòng)
1 在內(nèi)核中配置I2C 驅(qū)動(dòng) Linux-2.6.32.2 對(duì)S2C2440 的I2C 接口提供了完善的驅(qū)動(dòng),因此我們只需在內(nèi)核中配置一下即可使用。 在內(nèi)核源代碼目錄執(zhí)行:make menuconfig,進(jìn)入內(nèi)核配置主菜單,依次選擇進(jìn)入如下子菜單: Device Drivers --- * I2C support --- I2C Hardware Bus support --- 如圖,我們看到這里已經(jīng)選擇好了“ * S3C2410 I2C Driver”,這里的S3C2410 也可以適用于S3C2440,因?yàn)樗鼈兊腎2C 端口及寄存器定義都是完全相同的。 以上配置所對(duì)
[單片機(jī)]
<font color='red'>linux</font>-2.6.32在mini2440開發(fā)板上移植 移植I2C-EEPROM <font color='red'>驅(qū)動(dòng)</font>
友善之臂Mini2440之嵌入式Linux下Nand Flash驅(qū)動(dòng)分析
一、Nand Flash驅(qū)動(dòng)源碼文件含義 在Linux內(nèi)核中,MTD源代碼放在/driver/mtd目錄下,該目錄中包含chips、devices、maps、nand、onenand和ubi六個(gè)子目錄。其中只有nand和onenand目錄中的代碼才與Nand驅(qū)動(dòng)有關(guān),nand目錄中的代碼比較通用,而onenand目錄中的代碼相對(duì)于nand中的代碼而言簡(jiǎn)化了許多,是三星公司開發(fā)的另類nand Flash。市場(chǎng)占有率不是很高。所以,開發(fā)基于MTD的nand驅(qū)動(dòng)程序,基本上只需要關(guān)注nand目錄了,包括Kconfig、Makefile以及如下重要文件: 1、nand_base.c 定義了Nand驅(qū)動(dòng)中對(duì)nand芯片最基本的操
[單片機(jī)]
關(guān)于Linux下AT91SAM9261的RS485驅(qū)動(dòng)
AT91SAM9261和ATMEL其它型號(hào)的ARM處理器使用高度相似的USART外設(shè),因 而驅(qū)動(dòng)程序也具有高度的相似性,而且USART硬件支持485模式,用RTS信號(hào)作為485的收發(fā)控制。在使用中,只要將其置為485模式,其余的操作和 普通的232操作一模一樣,RTS的翻轉(zhuǎn)是自動(dòng)的。 我的板子上使用USART0擴(kuò)展了一個(gè)485接口,而Linux原有串口驅(qū)動(dòng)只支持普通的232模式,為了在Linux下方便地使用485接口,需要對(duì)原來(lái)的驅(qū)動(dòng)程序稍加改動(dòng)。 有關(guān)的文件 arch/arm/mach-at91/目錄下: at91sam9261_devices.c中的相關(guān)函數(shù)(不用改): at91_add_device_serial()
[單片機(jī)]
Linux2.6.32移植到MINI2440(4)移植+分析DM9000網(wǎng)卡驅(qū)動(dòng)
開發(fā)環(huán)境: 主機(jī):fedora 14 虛擬機(jī):vmware workstation 10 交叉編譯工具:arm-linux-gcc 4.3.2 開發(fā)板:mini2440(2m nor ,64m sdram,256m nand) 內(nèi)核版本:linux2.6.32.2 上一篇帖子的uImage可以起yaffs2文件系統(tǒng),但是起不了nfs,我的yaffs2使用nfs打包來(lái)的,換一個(gè)內(nèi)核可以起,bootargs也沒(méi)有問(wèn)題,可能是這里網(wǎng)卡沒(méi)有移植造成的,移植結(jié)束之后再看能不能起,因?yàn)閚fs對(duì)后面做驅(qū)動(dòng)開發(fā)優(yōu)勢(shì)比較大,方便調(diào)試看現(xiàn)象,不需要每次都燒寫進(jìn)去,所以還是需要能夠起nfs的。DM9000內(nèi)核
[單片機(jī)]
<font color='red'>Linux</font>2.6.32移植到MINI2440(4)移植+分析DM9000網(wǎng)卡<font color='red'>驅(qū)動(dòng)</font>
編譯基于ARM LINUX驅(qū)動(dòng)模塊的Makefile
KERNELDIR = /home/wenhao/platform/linux-2.6.34 PWD := $(shell pwd) CROSS_COMPILE = /usr/local/arm/4.3.2/bin/arm-linux- CC = $(CROSS_COMPILE)gcc obj-m := key.o modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions .PHONY: modules clean
[單片機(jī)]
s3c2410觸摸屏在linux下的驅(qū)動(dòng)分析 一
觸摸屏驅(qū)動(dòng)在/kernel/drivers/char/s3c2410-ts.c 文件中。 該驅(qū)動(dòng)總要有以下重要數(shù)據(jù)結(jié)構(gòu): 1.觸摸屏的file_operations static struct file_operations s3c2410_fops={ owner: THIS_MODULE, open: s3c2410_ts_open, read: s3c2410_ts_read, release: s3c2410_ts_release, #ifdef USE_ASYNC fasync: s3c2410_ts_fasync, #endif poll: s3c2410_ts_poll, }; 2.全局變量T
[單片機(jī)]
小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號(hào)

 
EEWorld服務(wù)號(hào)

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號(hào) 京ICP備10001474號(hào)-1 電信業(yè)務(wù)審批[2006]字第258號(hào)函 京公網(wǎng)安備 11010802033920號(hào) Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 甘孜县| 金门县| 香格里拉县| 县级市| 禄丰县| 山西省| 雷山县| 浪卡子县| 星子县| 天门市| 广灵县| 白沙| 高邮市| 昆山市| 无极县| 额济纳旗| 汽车| 永德县| 韶关市| 巨野县| 漠河县| 黑河市| 板桥市| 蒲江县| 上栗县| 油尖旺区| 措美县| 郧西县| 浮山县| 昂仁县| 五大连池市| 广西| 盐边县| 中阳县| 新乡市| 原平市| 雅江县| 迁安市| 南昌县| 明星| 南京市|