在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > arm驅(qū)動(dòng)Linux內(nèi)核開發(fā)之阻塞非阻塞IO輪詢操作

            arm驅(qū)動(dòng)Linux內(nèi)核開發(fā)之阻塞非阻塞IO輪詢操作

            作者: 時(shí)間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
            《[arm驅(qū)動(dòng)]Linux內(nèi)核開發(fā)之阻塞非阻塞IO----輪詢操作》涉及內(nèi)核驅(qū)動(dòng)函數(shù)二個(gè),內(nèi)核結(jié)構(gòu)體零個(gè),分析了內(nèi)核驅(qū)動(dòng)函數(shù)二個(gè);可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)模板二個(gè),可參考的相關(guān)應(yīng)用程序模板或內(nèi)核驅(qū)動(dòng)一個(gè)

            一、概念:Poll是非阻塞IO----輪詢操作
            非阻塞 I/O 的應(yīng)用程序常常使用 poll, select, 和 epoll 系統(tǒng)調(diào)用. poll, select 和 epoll 本質(zhì)上有相同的功能: 每個(gè)允許一個(gè)進(jìn)程來決定它是否可讀或者寫一個(gè)或多個(gè)文件而不阻塞.

            本文引用地址:http://www.biyoush.com/article/201611/318225.htm

            Tip:select()和poll(),epoll查詢是否可對(duì)設(shè)備進(jìn)行無阻塞的訪問,這幾個(gè)系統(tǒng)調(diào)用最終又會(huì)引發(fā)設(shè)備驅(qū)動(dòng)中的poll()函數(shù)被執(zhí)行

            PS:看到這感覺暈了,暫且不理會(huì)
            二、使用場(chǎng)景:
            它們常常用在必須使用多輸入輸出流的應(yīng)用程序(如調(diào)用read,write字符設(shè)備驅(qū)動(dòng)文件/dev/****)。因?yàn)檫@些調(diào)用也可阻塞進(jìn)程直到任何一個(gè)給定集合的文件描述符可用來讀或?qū)?
            三、相關(guān)函數(shù)
            1、內(nèi)核函數(shù)
            內(nèi)核驅(qū)動(dòng)函數(shù)一)a)poll()函數(shù)原型:

            unsigned int (*poll) (struct file *filp, poll_table *wait);

              作用:調(diào)用poll_wait(),將可能引起設(shè)備文件狀態(tài)變化的等待隊(duì)列頭添加到poll_table.
            返回值:返回是否能對(duì)設(shè)備進(jìn)行無阻塞讀寫訪問的掩碼

            放回值mask常量及函數(shù)

            常量 說明
            POLLIN 普通或優(yōu)先級(jí)帶數(shù)據(jù)可讀
            POLLRDNORM 普通數(shù)據(jù)可讀
            POLLRDBAND 優(yōu)先級(jí)帶數(shù)據(jù)可讀
            POLLPRI 高優(yōu)先級(jí)數(shù)據(jù)可讀
            POLLOUT 普通數(shù)據(jù)可寫
            POLLWRNORM 普通數(shù)據(jù)可寫
            POLLWRBAND 優(yōu)先級(jí)帶數(shù)據(jù)可寫
            POLLERR 發(fā)生錯(cuò)誤
            POLLHUP 發(fā)生掛起
            POLLNVAL 描述字不是一個(gè)打開的文件

            內(nèi)核驅(qū)動(dòng)函數(shù)二)b)poll_wait()函數(shù)原型:

            void poll_wait(struct file *filp, wait_queue_head_t *queue, poll_table *wait);

            作用:將可能引起設(shè)備文件狀態(tài)變化的等待隊(duì)列頭添加到poll_table
            2、應(yīng)用程序poll函數(shù)

            int poll(struct pollfd *fds, nfds_t nfds, int timeout)

            a)參數(shù):
            fds 指向 struct pollfd 數(shù)組
            nfds 指定 pollfd 數(shù)組元素的個(gè)數(shù),也就是要監(jiān)測(cè)幾個(gè) pollfd
            timeout 時(shí)間參數(shù),單位ms,1000ms=1s
            Tip:fds可以是很多個(gè)文件(如網(wǎng)卡,按鍵),poll可以論尋fds[n]
            b)結(jié)構(gòu)體pollfd
            struct pollfd {
            int fd;
            short events;
            short revents;
            };

            3、總結(jié):從應(yīng)用程序的調(diào)用來看,并不需要理會(huì)內(nèi)核函數(shù)中的參數(shù)poll_table *wait是什么,只需要調(diào)用poll_wait()

            四、使用模板
            模板一)a)內(nèi)核程序模板

            static DECLARE_WAIT_QUEUE_HEAD(waitq);//定義結(jié)構(gòu)體名稱為waitq
            poll(struct file *file, poll_table *wait){//返回mask
            unsigned int mask = 0;
            poll_wait(file, &waitq, wait);
            if(...)//可讀

            mask |= POLLIN | POLLRDNORM; //標(biāo)識(shí)數(shù)據(jù)可獲得

            if(...)//可寫

            mask |= POLLOUT | POLLRDNORM; //標(biāo)識(shí)數(shù)據(jù)可寫入

            return mask;
            }

            模板二)b)測(cè)試程序模板

            struct pollfd fds[n];
            fds[0].fd = fd;
            fds[0].events = POLLIN;
            poll(fds, n, 5000);

            c)再次理解下面幾句
            fds 指向 struct pollfd 數(shù)組
            nfds 指定 pollfd 數(shù)組元素的個(gè)數(shù),也就是要監(jiān)測(cè)幾個(gè) pollfd
            timeout 時(shí)間參數(shù),單位ms,1000ms=1s
            Tip:fds可以是很多個(gè)文件(如網(wǎng)卡,按鍵),poll可以論尋fds[n]

            實(shí)例一)五、案例jz2440中斷非阻塞驅(qū)動(dòng)實(shí)例

            1、 非阻塞內(nèi)核按鍵驅(qū)動(dòng)。

            //“irq_drv”,"irq_","irq"
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            #include
            static DECLARE_WAIT_QUEUE_HEAD(button_waitq);//定義結(jié)構(gòu)體名稱為button_waitq
            static struct class *irq_class;
            static struct class_device *irq_class_dev;
            static int ev_press = 0;
            static unsigned char key_val;
            struct pin_desc{
            unsigned int pin;
            unsigned int key_val;
            };
            struct pin_desc pins_desc[3] = {
            {S3C2410_GPF0, 0x01},
            {S3C2410_GPF2, 0x02},
            {S3C2410_GPG3, 0x03},
            };
            static irqreturn_t irq_handle(int irq, void *dev__id){
            //printk("irq = %dn", irq);
            int pinval;
            struct pin_desc *pindesc = (struct pin_desc *)dev__id;
            pinval = s3c2410_gpio_getpin(pindesc->pin);
            if(!pinval){//按下
            key_val = pindesc->key_val;
            }else{//松開
            key_val = 0x80 | pindesc->key_val;
            }
            ev_press = 1;
            wake_up_interruptible(&button_waitq);
            return IRQ_RETVAL(IRQ_HANDLED);//warn:返回IRQ_HANDLED
            }
            static unsigned irq_drv_poll(struct file *file, poll_table *wait)
            {
            unsigned int mask = 0;
            poll_wait(file, &button_waitq, wait); // 不會(huì)立即休眠
            if (ev_press)
            mask |= POLLIN | POLLRDNORM;
            return mask;
            }
            static int irq_drv_open(struct inode *inode, struct file *file)
            {
            printk("irq_dev readn");
            // request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char * devname, void * dev_id); dev_id隨意
            request_irq(IRQ_EINT0, irq_handle, IRQ_TYPE_EDGE_BOTH, "s2", &pins_desc[0]);
            request_irq(IRQ_EINT2, irq_handle, IRQ_TYPE_EDGE_BOTH, "s3", &pins_desc[1]);
            request_irq(IRQ_EINT11, irq_handle, IRQ_TYPE_EDGE_BOTH, "s4", &pins_desc[2]);
            return 0;
            }
            static ssize_t irq_drv_read (struct file *file, char __user *buf, size_t count, loff_t *ppos){
            if(count != 1)return -EINVAL;
            wait_event_interruptible(button_waitq, ev_press);//ev_press標(biāo)志(if!(ev_press)),那么一直休眠
            copy_to_user(buf, &key_val, 1);//一個(gè) char 0xff
            ev_press = 0;
            return 1;//warn :return the size of val
            }
            static ssize_t irq_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
            {
            printk("irq_dev writen");
            return 0;
            }
            static ssize_t irq_drv_release(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]);
            return 0;
            }
            static struct file_operations irq_drv_fops = {
            .owner = THIS_MODULE, /* 這是一個(gè)宏,推向編譯模塊時(shí)自動(dòng)創(chuàng)建的__this_module變量 */
            .open = irq_drv_open,
            .write = irq_drv_write,
            .read = irq_drv_read,
            .release = irq_drv_release,
            .poll = irq_drv_poll,
            };
            int major;
            static int irq_drv_init(void)
            {
            major = register_chrdev(0, "irq_drv", &irq_drv_fops); // 注冊(cè), 告訴內(nèi)核
            if (major < 0) {
            printk(" cant register major numbern");
            return major;
            }
            irq_class = class_create(THIS_MODULE, "irq_drv");
            if (IS_ERR(irq_class))
            return PTR_ERR(irq_class);
            irq_class_dev = class_device_create(irq_class, NULL, MKDEV(major, 0), NULL, "irq"); /* /dev/xyz */
            if (IS_ERR(irq_class_dev))
            return PTR_ERR(irq_class_dev);
            return 0;
            }
            static void irq_drv_exit(void)
            {
            unregister_chrdev(major, "irq_drv"); // 卸載
            class_device_unregister(irq_class_dev);
            class_destroy(irq_class);
            }
            module_init(irq_drv_init);
            module_exit(irq_drv_exit);
            MODULE_LICENSE("GPL");

            2、測(cè)試應(yīng)用程序

            #include
            #include
            #include
            #include
            #include
            #include
            /* irq
            */
            int main(int argc, char **argv)
            {
            int fd;
            unsigned char key_val;
            int cnt = 0;
            int ret;
            struct pollfd fds[1];
            fd = open("/dev/irq", O_RDWR);
            if (fd < 0)
            {
            printf("cant open!n");
            exit(1);
            }
            fds[0].fd = fd;
            fds[0].events = POLLIN;
            while (1)
            {
            ret = poll(fds, 1, 5000);
            if(ret == 0){
            printf("time out!n");
            }else{
            read(fd, &key_val, 1);
            printf("key_Vals = 0x%xn", key_val);
            }
            }
            return 0;
            }
            Makefile
            #myirq.bin
            objs := $(patsubst %c, %o, $(shell ls *.c))
            myarmgcc := /workspacearm/armlinuxgcc2626/bin/arm-linux-gcc
            myirq.bin:$(objs)
            $(myarmgcc) -o $@ $^
            cp *.bin /opt/fsmini/
            %.o:%.c
            $(myarmgcc) -c -o $@ $<
            clean:
            rm -f *.bin *.o

            Curtiss Falcon



            評(píng)論


            技術(shù)專區(qū)

            關(guān)閉