分类: LINUX

poll函数用于监测多个等待事件,若事件未发生,进程睡眠,放弃CPU控制权,若监测的任何一个事件发生,poll将唤醒睡眠的进程,并判断是什么等待事件发生,执行相应的操作。poll函数退出后,struct pollfd变量的所有值被清零,需要重新设置。

示例是使用poll函数来监测按键的输入

----------------------------------------------------------------------------------------------------------

 

驱动代码:

  1. #include <linux/config.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>
  4. #include <linux/fs.h>
  5. #include <linux/init.h>
  6. #include <linux/devfs_fs_kernel.h>
  7. #include <linux/miscdevice.h>
  8. #include <linux/delay.h>
  9. #include <asm/irq.h>
  10. #include <asm/arch/regs-gpio.h>
  11. #include <asm/hardware.h>
  12. #include <linux/cdev.h>
  13. #include <linux/mm.h>
  14. #include <linux/interrupt.h>
  15. #include <linux/poll.h>
  16. #include <asm/uaccess.h>
  17. #include <asm/ioctl.h>
  18. #include <asm/arch/regs-irq.h>
  19. #include <asm/io.h>
  20. #define key S3C2410_GPF0
  21. #define key_irq IRQ_EINT0 //IRQ_EINT0是中断号
  22. #define key_cfg S3C2410_GPF0_EINT0 //设置为外部中断功能
  23. #define DEVICE_NAME "key"
    //注意加上双引号
  24. #define DEVICE_MAJOR major
  25. #define DEVICE_MINOR 0
  26. static dev_t dev;
    //dev_t类型用于存放主设备号和次设备号
  27. static
    int major;
  28. struct cdev *p_cdev;
    //声明一个指向字符设备结构的指针
  29. static
    int key_event=0;
    时满足唤醒条件,静态全局变量
  30. static
    int key_value=1;
    //按键键值
  31. static DECLARE_WAIT_QUEUE_HEAD(wq);
    //调用宏定义,静态创建一个名为wq的等待队列
  32. static
    void key_interrupt(void)
    //中断处理函数,注册中断时已注册了中断程序的入口地址
  33. {
  34.  key_value=s3c2410_gpio_getpin(key);
  35.  key_event=1;
    //唤醒标记置位,表示条件达到,可以唤醒进程继续执行
  36.  wake_up_interruptible(&wq);
    //调用宏定义,唤醒标记置位后调用此函数,&wq是队列入口地址
  37. }
  38. static
    int key_read(struct
    file
    *filp,char __user *buff,size_t count,loff_t *offp)
  39. {
  40. ,从此处将进程放入wq等待队列休眠,等待中断;key_event==1时,此宏不执行操作
  41. //调用poll的时候来等待,这里可以不用wait_event_interrupt()
  42.  key_value=s3c2410_gpio_getpin(key);
  43.  copy_to_user(buff,&key_value,sizeof(key_event));
    //将&key_value地址的值从内核空间复制到用户空间
  44.  key_event=0;
    //完成中断操作,将唤醒标记清零,继续休眠
  45.  return 0;
  46. }
  47. static unsigned int key_poll(struct
    file
    *filp,poll_table *wait)
  48. {
  49.  unsigned int mask=0;
    //用来记录发生的事件,以unsigned int类型返回
  50.  poll_wait(filp,&wq,wait);
    //将当前进程添加到wq等待队列中
  51.  if(key_event==1)mask|=POLLIN|POLLRDNORM;
    //中断事件发生,这时有数据可读,在mask中标记是可读事件发生
  52.  return mask;
    则表示等待事件超时
  53. }
  54. //设置寄存器,申请中断号等在open函数中完成
  55. static
    int key_open(struct inode *inode,struct
    file
    *filp)
  56. {
  57.  int ret;
  58.  s3c2410_gpio_cfgpin(key,key_cfg);
    //设置引脚功能
  59.  s3c2410_gpio_pullup(key,1);
    为禁止内部上拉
  60.  ret=request_irq(key_irq,(void
    *)key_interrupt,SA_INTERRUPT,DEVICE_NAME,NULL);
    //注册中断,中断不共享时最后一个参数为NULL
  61.  if(ret)
    {
  62.   printk("Could not register interrupt\n");
  63.   return ret;
  64.  }
  65.  set_irq_type(key_irq,IRQT_BOTHEDGE);
    //设置中断方式为双边触发
  66.  return 0;
  67. }
  68. static
    int key_close(struct inode *inode,struct
    file
    *filp)
  69. {
  70.  free_irq(key_irq,NULL);
    //中断无共享时第二个参数为NULL
  71.  return 0;
  72. }
  73. static
    struct file_operations key_fops={
  74.  .owner=THIS_MODULE,
  75.  .open=key_open,
  76.  .release=key_close,
  77.  .read=key_read,
  78.  .poll=key_poll,
  79. };
  80. int key_init(void)
  81. {
  82.  int ret;
  83.  ret=alloc_chrdev_region(&dev,DEVICE_MINOR,1,DEVICE_NAME);
    //采用主设备号动态分配
  84.  if(ret<0){
  85.   printk("Register /dev/key failed!\n");
  86.   return ret;
  87.  }
  88.  else printk("Register /dev/key successfully!\n");
  89.  major=MAJOR(dev);
    //取得分配到的主设备号
  90.  p_cdev=cdev_alloc();
    //申请一个字符设备结构并返回指向它的指针
  91.  cdev_init(p_cdev,&key_fops);
    //相当于p_cdev->ops=&key_fops
  92.  p_cdev->owner=THIS_MODULE;
  93.  ret=cdev_add(p_cdev,dev,1);
    //向系统添加这个字符设备
  94.  if(ret<0){
  95.   printk("Add cdev failed!\n");
  96.   return ret;
  97.  }
  98.  devfs_mk_cdev(dev,S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,DEVICE_NAME);
  99.  return 0;
  100. }
  101. void key_exit(void)
  102. {
  103.  unregister_chrdev_region(dev,1);
  104.  cdev_del(p_cdev);
    //删除字符设备
  105.  devfs_remove(DEVICE_NAME);
  106.  printk("Device unregister!\n");
  107. }
  108. MODULE_LICENSE("GPL");
  109. MODULE_AUTHOR("HJW");
  110. module_init(key_init);
  111. module_exit(key_exit);
  112. ---------------------------------------------------------------------------------------------------
  113. 测试程序代码:
  114. #include <stdio.h>
  115. #include <stdlib.h>
  116. #include <unistd.h>
  117. #include <sys/ioctl.h>
  118. #include <sys/types.h>
  119. #include <sys/stat.h>
  120. #include <fcntl.h>
    /*文件控制*/
  121. #include <sys/select.h>
  122. #include <sys/time.h>
    /*时间方面的函数*/
  123. #include <errno.h>
    /*有关错误方面的宏*/
  124. #include<sys/poll.h>
    //poll()
  125. #include<fcntl.h>
  126. #include<string.h>
    //memset()
  127. int main(void)
  128. {
  129.  int fd,key_value,ret;
  130.  struct pollfd event;
    //创建一个struct pollfd结构体变量,存放文件描述符、要等待发生的事件
  131.  fd=open("/dev/key",O_RDWR);
  132.  if(fd<0){
  133.   perror("open /dev/key error!\n");
  134.   exit(1);
  135.  }
  136.  printf("open /dev/key sucessfully!\n");
  137.  while(1){
    //poll结束后struct pollfd结构体变量的内容被全部清零,需要再次设置
  138.   memset(&event,0,sizeof(event));
    //memst函数对对象的内容设置为同一值
  139.   event.fd=fd;
    //存放打开的文件描述符
  140.   event.events=POLLIN;
    //存放要等待发生的事件
  141.   ret=poll((struct pollfd *)&event,1,5000);
    毫秒后超时,-1为无限等待
  142. 是设定的时间超时,整数表示等待的时间发生
  143.   if(ret<0){
  144.    printf("poll error!\n");
  145.    exit(1);
  146.   }
  147.   if(ret==0){
  148.    printf("Time out!\n");
  149.    continue;
  150.   }
  151.   if(event.revents&POLLERR){
    //revents是由内核记录的实际发生的事件,events是进程等待的事件
  152.    printf("Device error!\n");
  153.    exit(1);
  154.   }
  155.   if(event.revents&POLLIN){
  156.    read(fd,&key_value,sizeof(key_value));
  157.    printf("Key value is '%d'\n",key_value);
  158.   }
  159.  }
  160.  close(fd);
  161.  return 0;
  162. }

poll()函数的使用的更多相关文章

  1. linux poll函数

    poll函数与select函数差不多 函数原型: #include <poll.h> int poll(struct pollfd fd[], nfds_t nfds, int timeo ...

  2. poll函数

    poll函数与select函数的功能基本一样,其定义如下: #include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int ...

  3. select与poll函数介绍

    select与poll函数介绍 在所有依从POSIX的平台上,select函数使我们可以执行I/O多路转接.传向select的参数告诉内核: 1)我们所关心的描述符 2)对于每个描述符我们所关心的状态 ...

  4. I/O多路复用——select函数与poll函数

    1 区别 同:(1)机制类似,本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理.(2)包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就 ...

  5. poll函数和串口设置

    2015.1.24 今天星期六,多云,早晨8:17起床的,今天是来南京起床最迟的一天,因为昨晚睡得有点迟,今天又不用上课,整个人有点放松.收拾好来到教室,教室门没有开,胡明也到了,其他人还在宿舍睡觉, ...

  6. [转载] poll()函数

    原地址:http://baike.baidu.com/view/2997591.htm   poll()函数:这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,下面是这个函 ...

  7. I/O多路转接之poll 函数

    poll 一.poll()函数: 这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,自认为poll和select大同小异,下面是这个函数的声明: #include < ...

  8. UNIX网络编程——select函数的并发限制和 poll 函数应用举例

    一.用select实现的并发服务器,能达到的并发数,受两方面限制 1.一个进程能打开的最大文件描述符限制.这可以通过调整内核参数.可以通过ulimit -n来调整或者使用setrlimit函数设置,  ...

  9. 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数

    本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...

随机推荐

  1. 多Web服务器之间共享Session的解决方案

    一.提出问题: 为了满足足够大的应用,满足更多的客户,于是我们架设了N台Web服务器(N>=2),在多台Web服务器的情况下,我们会涉及到一个问题:用户登陆一台服务器以后,如果在跨越到另一台服务 ...

  2. XAF 如何将数据库中Byte array图片显示出来

    问题比较简单,直接上代码. private Image _Cover; [Size(SizeAttribute.Unlimited), ValueConverter(typeof(ImageValue ...

  3. Java 序列化Serializable详解

    Java 序列化Serializable详解(附详细例子) Java 序列化Serializable详解(附详细例子) 1.什么是序列化和反序列化Serialization(序列化)是一种将对象以一连 ...

  4. 浅谈sql的字符分割

    对于oracle:在字符串处理时:经常会遇到字符串分割的问题:可惜SQL中没有split函数:这个倒是挺困扰我们写sql的.对此:我来说说这字符串分割. 例如对字段str中一条数据是'120-mm-2 ...

  5. html标签快速转换思想方法

    function htmlencode(s){ var div = document.createElement('div'); div.appendChild(document.createText ...

  6. web项目开发规范整理总结

    一.类.函数.变量名命名: 1.定义类时,全部拼音的首字母必须大写:如Person,ClassDemo:(帕斯卡命名法):也可以用带下斜杆的匈牙利命名法进行命名,如    head_navigatio ...

  7. 关于php留言本网站的搭建

    1.检查php,http服务是否安装 [root@localhost ~]# rpm -qa | grep http httpd-tools--.el7.centos.x86_64 httpd--.e ...

  8. King's Quest —— POJ1904(ZOJ2470)Tarjan缩点

    King's Quest Time Limit: 15000MS Memory Limit: 65536K Case Time Limit: 2000MS Description Once upon ...

  9. Codeforces Round #363 (Div. 2)A-D

    699A 题意:在一根数轴上有n个东西以相同的速率1m/s在运动,给出他们的坐标以及运动方向,问最快发生的碰撞在什么时候 思路:遍历一遍坐标,看那两个相邻的可能相撞,更新ans #include< ...

  10. response项目的各个写法

    这个是一个响应式的页面 原文可参照:http://localhost/response/seejs_index.html