linux 驱动学习之poll与select
2012-12-03 18:04
344 查看
在使用socket或串口的时候应用代码经常使用select来判断有没接收到数据,驱动需要做什么处理,应用层用户才能正确判断有数据收到并读取数据呢?使用select能够监视我们需要监视的文件描述符的变化情况——读写或是异常。
先建立简单模型,应用使用select监听设备是否可读,当设备可读将数据读出后继续监听。已经有了一个监听设备可读状态的进程,还要打开终端使用echo xxx >/dev/moddev60向设备写入数据,设备驱动收到数据后控制设备变成可读状态,select进程select函数返回,查询设备可读后读出数据。代码为了演示做了简化不做并发出错处理等。
先看下应用c代码
驱动关键代码
先建立简单模型,应用使用select监听设备是否可读,当设备可读将数据读出后继续监听。已经有了一个监听设备可读状态的进程,还要打开终端使用echo xxx >/dev/moddev60向设备写入数据,设备驱动收到数据后控制设备变成可读状态,select进程select函数返回,查询设备可读后读出数据。代码为了演示做了简化不做并发出错处理等。
先看下应用c代码
#include <stdio.h> #include <fcntl.h> unsigned char rdBuf[1024]; int main (int *argc,char**argv) { int fd,res; fd_set fset; FD_ZERO(&fset); fd=open("/dev/moduledev60",O_RDWR); if(fd<0){ printf("open devices error\n"); return -1; } while(1) { FD_ZERO(&fset); FD_SET(fd,&fset); res=select(fd+1,&fset,NULL,NULL,NULL); if(res==-1) { close(fd); return -1; } else if(res==0) break; else { /*select 返回后判断可读*/ if(FD_ISSET(fd,&fset)) { read(fd,rdBuf,1024); printf("read data:%s\n",rdBuf); } } } close(fd); return 0; }
驱动关键代码
struct file_operations ops= { .owner=THIS_MODULE , .read =fileops_read , .write=fileops_write, .poll =fileops_poll };
DECLARE_WAIT_QUEUE_HEAD(rdWait);//poll_wait中使用 static unsigned char rdBuf[1024];//测试用读写缓存 写入数据和读取数据0结尾 static unsigned char rdFlag=0; //可读标记 0不可读缓存内无数据 1可读 ssize_t fileops_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { unsigned int len; if(rdFlag==0) return 0; //不可读时直接返回 len=strlen(rdBuf); //读缓存字符串长 这个模型只做字符串(0结尾)的写入和读取 copy_to_user(buff,rdBuf,len); // rdFlag=0; //清标记 return len; } ssize_t fileops_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp) { copy_from_user(rdBuf,buff,count);// rdBuf[count]=0; //补字符串结束标记 rdFlag=1; //标记可读 poll函数检测这个标记 wake_up_interruptible(&rdWait); /*fileops_poll 函数使用了 poll_wait 加入了rdWait等待列队,执行后fileops_poll会被调用,如果不使用等待列队 fileops_poll只在应用调用select时执行一次 这样有数据select也不会返回*/ return count; } unsigned int fileops_poll(struct file *filp,poll_table *wait) { /*这里测试只处理的可读标记 也可以增加可写标记*/ int mask=0; poll_wait(filp,&rdWait,wait); //这个函数不阻塞的,当状态改变时,应该唤醒列队这个函数才会重新调用更新新的状态。 if(rdFlag) { mask=POLLIN|POLLRDNORM; } return mask; }
编译后测试结果 先运行应用,监听设备是否可读 [root@localhost ctest]# ./main 打开另外一个终端,写入数据 [root@localhost ctest]# echo eeee>/dev/moduledev60 [root@localhost ctest]# echo eeee>/dev/moduledev60 [root@localhost ctest]# echo eeee>/dev/moduledev60 应用判断到可读后读出数据 [root@localhost ctest]# ./main read data:eeee read data:eeee read data:eeee
相关文章推荐
- Linux驱动学习8(非阻塞IO的实现--select/poll方法)
- 网络编程中select模型和poll模型学习(linux)
- libevent库源码学习-poll/select( linux)
- Linux 设备驱动--- Poll 方法 --- Select【转】
- Linux设备驱动程序第三版学习(7)- 高级字符驱动程序操作(续2)- poll/select
- linux驱动开发--字符设备:设备轮询操作select/poll
- 【Linux驱动】轮询操作select()和poll()
- 转载_linux驱动中的poll 和 用户空间的select
- Linux高级字符设备驱动 poll方法(select多路监控原理与实现)
- 字符设备驱动学习笔记--按键驱动深化:poll或select操作
- 【Linux 驱动】第六章 高级字符驱动程序操作----poll,select,epoll
- Linux学习:多路复用 select / poll
- Linux 设备驱动--- Poll 方法 --- Select
- Linux 内核驱动--阻塞与非阻塞机制及Poll/Select分析
- libevent库源码学习-poll/select( linux) .devpoll(/dev/poll)( linux) ,epoll(linux)
- linux高级字符设备驱动之 四 poll方法(select多路监控原理与实现)
- LINUX 网络编程---多路复用和信号驱动I/O(王德仙)2012-04-07 客户端和服务器端编写完成,明天开始学习poll 和epoll
- Linux学习笔记(06-11)select, poll和epoll的区别
- Linux 内核驱动--阻塞与非阻塞机制及Poll/Select分析if
- Linux高级字符设备驱动 poll方法(select多路监控原理与实现)