(十一)linux之poll轮询
目錄
- (一)poll輪詢的作用
- (二)poll輪詢相關(guān)的接口
- (三)poll使用流程
- (四)實(shí)例代碼
(一)poll輪詢的作用
以阻塞的方式打開文件,那么對(duì)多個(gè)文件讀寫時(shí),若某個(gè)文件未準(zhǔn)備好,則系統(tǒng)會(huì)處于讀寫阻塞,并影響其他文件的讀寫,poll輪訓(xùn)就是實(shí)現(xiàn)既可使用輸入輸出流又不想阻塞在任何一個(gè)設(shè)備的讀寫操作
調(diào)用poll函數(shù)返回時(shí),會(huì)返回一個(gè)文件是否可讀寫的標(biāo)志狀態(tài),用戶程序根據(jù)不同的標(biāo)志狀態(tài)來(lái)讀寫相應(yīng)的文件,實(shí)現(xiàn)阻塞方式打開但是非阻塞方式讀寫的結(jié)果
(二)poll輪詢相關(guān)的接口
請(qǐng)求事件和返回事件類型:
POLLIN There is data to read. POLLOUT Writing is now possible, though a write larger that the available spacein a socket or pipe will still block (unless O_NONBLOCK is set). POLLPRI: There is urgent data to read POLLERR: Error condition (only returned in revents; ignored in events).POLLHUP: Hang up (only returned in revents; ignored in events). POLLNVAL: Invalid request: fd not open (only returned in revents; ignored in events). POLLRDNORM Equivalent to POLLIN. POLLRDBAND Priority band data can be read (generally unused on Linux).POLLWRNOR Equivalent to POLLOUT.POLLWRBAND Priority data may be written. RETURN VALUE On success, a positive number is returned; this is the number of structures which havenonzero revents fields (in other words, those descriptors with events or errors reported).A value of 0 indicates that the call timed out and no file descriptors were ready. Onerror, -1 is returned, and errno is set appropriately.設(shè)置輪訓(xùn)的等待隊(duì)列poll_wait:
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) {if (p && p->_qproc && wait_address)p->_qproc(filp, wait_address, p); }喚醒等待隊(duì)列節(jié)點(diǎn)wake_up_interruptible或wake_up:
#define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL) void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key); /*** __wake_up - wake up threads blocked on a waitqueue.* @q: the waitqueue* @mode: which threads* @nr_exclusive: how many wake-one or wake-many threads to wake up* @key: is directly passed to the wakeup function** It may be assumed that this function implies a write memory barrier before* changing the task state if and only if any tasks are woken up.*/(三)poll使用流程
1.內(nèi)核層編寫poll相關(guān)的函數(shù)
unsigned int cdev_poll (struct file * fp, struct poll_table_struct * table)2.在合適cdev_poll函數(shù)中調(diào)用poll_wait
poll_wait(fp,&waithead,table);//不會(huì)進(jìn)行阻塞,添加等待隊(duì)列到輪詢列表中3.在合適的地方調(diào)用wake_up_interruptible喚醒poll等待隊(duì)列
wake_up_interruptible(&waithead)(四)實(shí)例代碼
假設(shè)要求創(chuàng)建多個(gè)設(shè)備節(jié)點(diǎn),每個(gè)設(shè)備節(jié)點(diǎn)對(duì)應(yīng)一個(gè)設(shè)備,在系統(tǒng)調(diào)用多次read接口來(lái)讀取底層設(shè)備的狀態(tài)。例如4個(gè)按鍵 ----- 4個(gè)設(shè)備節(jié)點(diǎn) ----分別讀取4個(gè)設(shè)備節(jié)點(diǎn)文件的數(shù)據(jù)獲取按鍵的狀態(tài)-----不確定哪一個(gè)按鍵被按下
分析:
若采用阻塞方式操作:四個(gè)讀寫操作會(huì)相互阻塞,如按鍵1未被按下,則讀取不到數(shù)據(jù),既是按鍵4被按下,也會(huì)被按鍵1的操作阻塞,獲取不到數(shù)據(jù)
若采用非阻塞操作:既是讀取不到數(shù)據(jù),也會(huì)直接返回,對(duì)于監(jiān)測(cè)按鍵的狀態(tài),按鍵隨時(shí)可能被按下,所以需要的是循環(huán)檢測(cè),采用非阻塞就會(huì)導(dǎo)致一直在進(jìn)行無(wú)用功
采用多路io輪詢操作:檢測(cè)是文件描述符是否發(fā)生變化,變化就去操作對(duì)應(yīng)的文件,否則阻塞在指定的操作
chrdev.c
chr_app.c
#include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <poll.h>int ret=0; struct pollfd fds[1]; char status[]={-1,-1,-1,-1}; char key[]={-1,-1,-1,-1}; int main(int argc, char *argv[]) {int i=0,fd= open(argv[1],O_RDWR/*|O_NONBLOCK*/);if(fd== -1){perror("open");return -1;}while(1){fds[0].fd = fd;fds[0].events = POLLIN;ret = poll(fds,1,5000);//只有錯(cuò)誤、滿足條件、超時(shí)才會(huì)返回,不滿足條件在這死等if(ret == -1){perror("poll\n");return -1;}else if(ret == 0){printf("timeout\n");}else if(ret & POLLIN){printf("ret >0\n");if(read(fd,status,4)<0)/*疑問(wèn):把read屏蔽掉打印出錯(cuò)*/{printf("按鍵狀態(tài)未改變\n");sleep(1);continue;}for(i=0;i<4;i++){if(status[i] != key[i] ){printf("key%d is %s\n",i,status[i]?"up":"down");status[i]=key[i];}}}}close(fd);return 0; }Makefile
CFLAG =-C TARGET = chrdev TARGET1 = chr_app KERNEL = /mydriver/linux-3.5 obj-m += $(TARGET).oall:make $(CFLAG) $(KERNEL) M=$(PWD)arm-linux-gcc -o $(TARGET1) $(TARGET1).c clean:make $(CFLAG) $(KERNEL) M=$(PWD) clean本文章僅供學(xué)習(xí)交流用禁止用作商業(yè)用途,文中內(nèi)容來(lái)水枂編輯,如需轉(zhuǎn)載請(qǐng)告知,謝謝合作
微信公眾號(hào):zhjj0729
微博:文藝to青年
總結(jié)
以上是生活随笔為你收集整理的(十一)linux之poll轮询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 啊怎么读 汉字发音指南?
- 下一篇: linux release 版本的区别,