zoukankan      html  css  js  c++  java
  • poll()函数的使用

    分类: 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; //唤醒中断的条件标记,1时满足唤醒条件,静态全局变量
    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. // wait_event_interruptible(wq,key_event); //key_event0,从此处将进程放入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; //返回事件记录,返回0则表示等待事件超时
    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); //第二个参数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 ");
    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! ");
    86.   return ret;
    87.  }
    88.  else printk("Register /dev/key successfully! ");
    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! ");
    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! ");
    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! ");
    134.   exit(1);
    135.  }
    136.  printf("open /dev/key sucessfully! ");
    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); //监测event,一个对象,等待5000毫秒后超时,-1为无限等待
    142. //判断poll的返回值,负数是出错,0是设定的时间超时,整数表示等待的时间发生
    143.   if(ret<0){
    144.    printf("poll error! ");
    145.    exit(1);
    146.   }
    147.   if(ret==0){
    148.    printf("Time out! ");
    149.    continue;
    150.   }
    151.   if(event.revents&POLLERR){ //revents是由内核记录的实际发生的事件,events是进程等待的事件
    152.    printf("Device error! ");
    153.    exit(1);
    154.   }
    155.   if(event.revents&POLLIN){
    156.    read(fd,&key_value,sizeof(key_value));
    157.    printf("Key value is '%d' ",key_value);
    158.   }
    159.  }
    160.  close(fd);
    161.  return 0;
    162. }
  • 相关阅读:
    如何破解“千人千面”,深度解读用户画像
    如何破解“千人千面”,深度解读用户画像
    AngularJS的简单入门
    Could not complete request
    AngularJS中angular.min.js:80 Error: [ng:areq] http://errors.angularjs.org/1.2.9/ng/areq
    BeanCreationException: Error creating bean with name 'transactionManager' defined
    Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
    Caused by: java.net.BindException: Address already in use: bind
    Linux的远程连接工具:SSH的安装
    虚拟机的安装
  • 原文地址:https://www.cnblogs.com/terrytian88/p/5893527.html
Copyright © 2011-2022 走看看