好久没有写驱动了,发现最简单的poll都不会写了

调试了一个下午,后来还是晚上回去查看了以前写的代码才调试好,其实很简单,就是差一点点了。不知到错在哪里。


本来是很简单的,要实现一个poll轮询,定义了file_operations的poll实现函数:

static unsigned int eventpoll(struct file *file, poll_table *wait)
{
    unsigned int mask = 0;

    poll_wait(file, &uart_wait, wait);
    
    printk("sclu have poll data\n");
    if(value > 0) {
        mask |= POLLIN | POLLRDNORM;
        value = 0;
    }   

    return mask;
}

这才是正确的,可是先前就是没有判断value>0的条件,弄得结果是,上层每次轮询都有结果返回,不断循环。

poll_wait只是把uart_wait注册到了等待队列上,然后返回;这是执行了一次eventpoll函数,这时候还没有休眠,休眠的时刻是eventpoll函数返回后,即调用eventpoll函数的地方,在文件系统的do_sys_poll函数中,用schedule_timeout让进程进入休眠;

以后就会进入休眠;

直到定时的时间到了,或者驱动中wake_up_interruptible唤醒对应的uart_wait;如果是前者,则直接返回用户空间;如果是后者,它醒来后再次进入eventpoll函数,看到value不为0,返回POLLIN的结果;或许你会问,第二次进来的时候不是又调用了一次poll_wait吗?是的,但是第二次调用返回到do_sys_poll函数时候,由于得到结果(POLLIN)了,所以要退出do_sys_poll函数了,这时候会调用poll_freewait(&table)释放掉资源,把结果返回用户空间

所以从poll开始到有数据到来wake up,一共执行两次eventpoll函数;如果是timeout,则只执行一次eventpoll函数。

可见,驱动中poll_wait的作用只是为了能让wake_up_interruptible能找到要唤醒的进程。没有poll_wait,进程到timeout后也一样能被唤醒;当然,如果用户空间设置time的时间为-1(即无限长),则不会被唤醒了。


还有read函数也出错啊:

static ssize_t gzsd_input_read(struct file *filp, char __user *buffer,int size, loff_t *ppos)
{

    char buf[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    buf[0] = value;
    printk("sclu %s\n", __FUNCTION__);
    if (copy_to_user(buffer, buf, sizeof(buf))) {
        printk("copy data to user err\n");
    }

    return sizeof(buf);
}

这是正确的,可是先前居然写成return 0,结果是上层每次read的结果都返回0,读不到数据,唉!

你可能感兴趣的:(好久没有写驱动了,发现最简单的poll都不会写了)