首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于Linux/Qtopia的车载温度网络采集 04

基于Linux/Qtopia的车载温度网络采集 04

3.2.2 读接口函数
  用户程序执行读操作的时候可能没有可以读取的数据,此时需要让read操作等待直到有数据可以读取。在此采用等待队列使进程在无数据读取时进入等待,数据到达时唤醒。等待队列设置成一个循环缓冲区,每放入一个新数据作为缓冲区的头,存放时间最久还未被取走的数据为缓冲区的尾。
  DS18B20_read( ) {
  DECLARE_WAITQUEUE(wait,current);//声明等待队列……
  Next_try:
  if(DS18B20dev.head != DS18B20dev.tail) {//等待队列不为空,即有数据
  DS18B20_ret=Read_Buffer_DS18B20(); //取走缓冲区的尾
  copy_to_user( ); //读取的数据送到用户空间
  }
  else { ……//等待队列为空,即没有数据
  add_wait_queue(&queue,&wait);
  current>state=TASK_INTERRUPTIBLE;//添加等待队列,声明状态为任务可中断
  while((DS18B20dev.head==DS18B20dev.tail)&&!signal_pending(current) {//进入等待
  schedule();
  current>state=TASK_INTERRUPTIBLE;
  }//如果缓冲区为空,Linux内核调度,等待通知
  current>state = TASK_RUNNING;//得到有数据的通知,声明任务状态为运行
  remove_wait_queue(&queue,&wait);//删除等待队列
  goto Next_try;//返回到读取数据
  }
  }
  3.2.3 fasync异步通知函数
  异步通知函数向进程发送SIGIO信号,通知访问设备的进程,表示设备已经准备好I/O读写了,避免主动查询,提高程序效率。使用异步通知需增加一个struct fasync_struct的结构指针,然后实现fasync接口函数。
  static struct fasync_struct *fasync;//定义一个结构体
  static int DS18B20_fasync(int fd,struct file *filp,int on) {//实现接口函数
  retval = fasync_helper(fd,filp,on,&fasync);
  if ( retval<0) return retval;return 0;
  }
  最后在需要向用户空间通知的地方调用内核的kill_fasync函数。在打开设备函数中提到的DS18B20Event()功能是:将数据放入循环缓冲区,唤醒等待队列并启动异步通知,其后两项功能是这样实现的:
  wake_up_interruptible(&queue);//唤醒等待队列
  if (fasync) {
  kill_fasync(&fasync,SIGIO,POLL_IN);//发送异步通知信号
  }
  3.2.4 poll系统调用操作接口函数
  当程序需要进行对多个文件读写时,如果某个文件没有准备好,则系统就会处于读写阻塞的状态,影响其他文件的读写。为了避免读写阻塞,使用poll函数。如果设备无阻塞地读,就返回POLLIN; 通常的数据已经准备好,可以读了,就返回POLLRDNORM。
  static unsigned int DS18B20_poll(struct file *flip, poll_table *wait) {
  poll_wait(flip,&queue,wait);
  if(DS18B20dev.head != DS18B20dev.tail) {
  return POLLIN|POLLRDNORM;
  }
  return 0;
  }
  3.2.5 release释放设备函数
  static intDS18B20_release(struct inode *inode,struct file *filp) {
  ReleaseFlag=0//内核停止读取温度标志
  DS18B20_fasync(1,filp,0);//关闭异步通知
  module_put(THIS_MODULE);//设备计数器减1
  return 0;
  }
  写接口函数用来通知驱动。例如通知驱动读取通道2的数据,在应用程序中执行写接口函数write(fileno,&SLOT2,1),驱动设置当前读通道号为2。
返回列表