linux 驱动学习之poll与select

        在使用socket或串口的时候应用代码经常使用select来判断有没接收到数据,驱动需要做什么处理,应用层用户才能正确判断有数据收到并读取数据呢?使用select能够监视我们需要监视的文件描述符的变化情况——读写或是异常。
       先建立简单模型,应用使用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


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值