新聞中心

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

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

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

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

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

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

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

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

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

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

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

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

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

        作用:將可能引起設(shè)備文件狀態(tài)變化的等待隊列頭添加到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ù)組元素的個數(shù),也就是要監(jiān)測幾個 pollfd
        timeout 時間參數(shù),單位ms,1000ms=1s
        Tip:fds可以是很多個文件(如網(wǎng)卡,按鍵),poll可以論尋fds[n]
        b)結(jié)構(gòu)體pollfd
        struct pollfd {
        int fd;
        short events;
        short revents;
        };

        3、總結(jié):從應(yīng)用程序的調(diào)用來看,并不需要理會內(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ù)據(jù)可獲得

        if(...)//可寫

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

        return mask;
        }

        模板二)b)測試程序模板

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

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

        實例一)五、案例jz2440中斷非阻塞驅(qū)動實例

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

        //“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); // 不會立即休眠
        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);//一個 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, /* 這是一個宏,推向編譯模塊時自動創(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); // 注冊, 告訴內(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、測試應(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



        評論


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

        關(guān)閉
        主站蜘蛛池模板: 鄂伦春自治旗| 普格县| 巴林右旗| 安阳市| 九台市| 山丹县| 苏尼特左旗| 山东| 十堰市| 友谊县| 类乌齐县| 陇川县| 姚安县| 永昌县| 孝昌县| 金溪县| 烟台市| 鄂伦春自治旗| 平乡县| 若羌县| 咸宁市| 福建省| 青浦区| 拉孜县| 鹤峰县| 石景山区| 西乡县| 铁力市| 濮阳县| 葵青区| 巴彦淖尔市| 盐池县| 闻喜县| 柳州市| 阿克苏市| 靖宇县| 余姚市| 云和县| 泰和县| 五常市| 江源县|