linux-2.6.22.6内核poll总结

1.为什么需要poll,其原因是当进行某些操作时,该操作会一直消耗cpu,浪费资源,所以引入poll可以让该进程在指定时间内如果没有结果产生(可以是某个操作或者获取数据)则进行休眠,这样就会释放cpu。

2.poll的执行流程为,当应用层调用poll函数时,会调用内核里面的sys_poll,sys_poll里的调用关系如下,也就是说最终通过do_pollfd这个函数去调用驱动的poll,如果驱动poll不返回0,则count++,在下面的if判断中成立,则跳出循环,并返回count,此时count不为0,代表有结果产生,如果为0,代表没有结果产生,应用层依次来判断是否继续某个操作。
在这里插入图片描述
3.举例来说:
驱动代码部分函数如下:


```c
**poll函数:**
static unsigned int s3c24xx_poll(struct file *file, poll_table *wait)
{
  unsigned int mask = 0;
	poll_wait(file, &button_waitq, wait); // 不会立即休眠

	if (ev_press)
		mask |= POLLIN | POLLRDNORM;

	return mask;
}

**按键中断处理函数:**
static irqreturn_t key_handle(int irq, void *dev_id)
{
    struct pin_desc * pindesc = (struct pin_desc *)dev_id;
      int  pin_val;

      pin_val = s3c2410_gpio_getpin(pindesc->pin_code);

      if(pin_val){ //松开
         key_val = (pindesc->pin_val | 0x80);

      }else{
        key_val = pindesc->pin_val;

      }

       ev_press = 1;                  /* 表示中断发生了 */
       wake_up_interruptible(&button_waitq);   /* 唤醒休眠的进程 */
      
       return IRQ_RETVAL(IRQ_HANDLED);
}

**按键值读取函数:**
static ssize_t s3c24xx_read(struct file *file, char __user *buf, size_t len, loff_t *ps){
 

    if(len != 1){

        printk("s3c24xx_read param err!");
        return -1;
    }
    /* 如果没有按键动作, 休眠 */
	  wait_event_interruptible(button_waitq, ev_press);

    copy_to_user(buf, &key_val, 1);
    ev_press = 0;
    return 1;
    
}

/* 这个结构是字符设备驱动程序的核心
 * 当应用程序操作设备文件时所调用的open、read、write等函数,
 * 最终会调用这个结构中指定的对应函数
 */
static struct file_operations s3c24xx_leds_fops = {
    .owner  =   THIS_MODULE,    
    .open   =   s3c24xx_open,     
    .read  =   s3c24xx_read,
    .poll  =   s3c24xx_poll,
};

应用代码:
int main(int argc, char **argv) {

  int fd;
  char val;
  struct pollfd fds[1];
  int ret;
  fd = open("/dev/key", O_RDWR);
  if (fd < 0) {
    printf("can't open!\n");
  }

  fds[0].fd     = fd;
	fds[0].events = POLLIN;

while(1){
   ret = poll(fds, 1, 5000);
		if (ret == 0)
		{
			printf("time out\n");
		}
		else
		{
			read(fd, &val, 1);
			printf("key_val = 0x%x\n", val);
		}

}
  

  return 0;
}

分析:在应用层里面,通过调用poll函数,根据其返回值来决定是否调用read函数读取数据,如果没有这个判断,那么在while循环里面会一直调用
read,可能有人会说,poll放在循环里面不也一样在一直消耗cpu吗,和read读取没啥区别啊,这里个人的理解是,poll可以监听多个应用,比如还有其他read的话,你也可以放在这一个poll里面监听(因为poll支持监听多个fd),这样就相当于一个poll监听多个read,等哪个好了就再去调用哪个,这肯定比多个read直接放在循环里读取更节省cpu资源。

注意:在中断处理函数key_handle里面,一定要 有wait_event_interruptible(button_waitq, ev_press)和 ev_press = 1; 这两个操作,分别是唤醒读取进程和设置中断标志,因为s3c24xx_poll里面是根据ev_press 来决定返回值的,而s3c24xx_poll又决定了do_pollfd的返回值,从而间接决定了sys_poll的返回值,这个返回值就是应用层判断的依据。
当然这是符合常理的,按下按键,代表有中断产生,就应该把休眠的读数进程唤醒,去读取按键值。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值