Char设备驱动程序中轮询机制的实现

时间:2017-04-15 10:22:50

标签: select module linux-kernel kernel linux-device-driver

Hello亲爱的stackoverflow参与者,

我是内核空间开发的新手,并且还处于起步阶段。 我开发了一个基本的char设备驱动程序,可以读取打开关闭等。但是找不到合适的来源以及如何教导Poll / select机制样本。

我在下面编写了民意调查功能的示例代码:

static unsigned int dev_poll(struct file * file, poll_table *wait)

{

poll_wait(file,&dev_wait,wait);
if (size_of_message > 0 ){
    printk(KERN_INFO "size_of_message > 0 returning POLLIN | POLLRDNORM\n");
    return POLLIN | POLLRDNORM;
}
else {
    printk(KERN_INFO "dev_poll return 0\n");
    return 0;
}

}

它工作正常,但无法解决一些问题。

当我从用户空间程序中调用select

    struct timeval time  = {5,0 } ;
select(fd + 1 , &readfs,NULL,NULL,&time);

驱动程序中的dev_poll函数调用一次并返回零或POLLIN以便缓冲区大小。然后再也没有打过电话。在用户空间中,如果dev_poll返回0,则在5秒后程序继续。 我无法理解的是,驱动程序代码将如何决定并让用户空间编程如果缓冲区中存在可读取的内容,这5秒钟,如果它被调用一次并立即返回。

在内核模块中是否有收集来自用户空间的timeval参数的信息?

谢谢你们。

此致

2 个答案:

答案 0 :(得分:0)

调用poll_wait()实际上将一些等待对象放入等待队列,指定为第二个参数。当等待对象被触发时(通过waitqueue' s wake_up或类似函数),将再次评估poll函数。

内核驱动程序无需担心超时:当时间结束时,等待对象将自动从等待队列中删除。

答案 1 :(得分:0)

你好,亲爱的好奇的人跟我一样关于民意调查。我想出了一个解决方案。

关于stackowerflow的另一个话题,一个人说如果内核需要持续的情况,则会多次调用poll_function。所以基本上我实现了那段代码。

当poll调用call wait_poll(wait_queue_head)时; 当设备有缓冲数据时(这通常在驱动程序写入功能中)。 用wait_queue_head参数调用wake_up宏。 所以在这一步之后再次调用驱动程序的轮询功能。 所以在这里你可以返回任何想要返回的内容。在这种情况下POLLIN | POLLRDNORM ..

以下是我在驱动程序中进行写入和轮询的示例代码。

    static unsigned int dev_poll(struct file * file, poll_table *wait)
{
    static int dev_poll_called_count = 0 ;
    dev_poll_called_count ++;
    poll_wait(file,&dev_wait,wait);
    read_wait_queue_length++;
    printk(KERN_INFO "Inside dev_poll called time is : %d read_wait_queue_length %d\n",dev_poll_called_count,read_wait_queue_length);

    printk(KERN_INFO "After poll_wait wake_up called\n");
    if (size_of_message > 0 ){
        printk(KERN_INFO "size_of_message > 0 returning POLLIN | POLLRDNORM\n");
        return POLLIN | POLLRDNORM;
    }
    else {
        printk(KERN_INFO "dev_poll return 0\n");
        return 0;
    }
}

    static ssize_t dev_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
    printk(KERN_INFO "Inside write \n");;
    int ret;    
    ret = copy_from_user(message, buffer, len);
    size_of_message = len ;
    printk(KERN_INFO "EBBChar: Received %zu characters from the user\n", size_of_message);
    if (ret)
        return -EFAULT;
    message[len] = '\0';
    printk(KERN_INFO "gelen string %s", message);
    if (read_wait_queue_length)
    {
        wake_up(&dev_wait);
        read_wait_queue_length = 0;
    }
    return len;   

}