2017-01-26 29 views
1

我正在为i2c连接温度/压力表写一个设备驱动程序。正确的接口非阻塞慢采样传感器驱动程序

要运行传感器,一旦首先请求新的读数。传感器将在一段时间内执行必要的采样,然后报告最终读数。这个过程预计需要一段时间。

用户空间预计将使用基于文件的文件read和可能的ioctl s使用字符设备接口连接到设备驱动程序。

我可以很容易地创建一个阻塞接口,用户线程尝试读取并保持阻塞状态,直到我能够报告传感器读数为止。

我想让驱动程序工作在非阻塞模式,因为采样预计需要一些时间。用户线程可以做其他的事情或阻止轮询/选择,直到采样完成。

问题是我需要read指示驱动程序开始采样,但驱动程序无法完成read,直到采样完成并处于非阻塞模式,驱动程序不允许阻塞这两者之间的线程状态。

作为一个额外的考虑,我想尽量减少调用来执行此操作的内核调用次数。我还需要确保宝贵的权力不会因不必要的抽样而浪费。

这样做的正确Linux模式是什么?

更新:我对实现细节不感兴趣,我真正关心的是遵循良好实践的用户/内核接口的设计。

+1

您是否已经在[LDD3](https://lwn.net/Kernel/LDD3/)[第6章(PDF)]中检出了示例字符驱动程序(https://lwn.net/images/pdf/ LDD3/ch06.pdf)?我个人会建议一个'read()'或'lseek()'尝试启动数据收集,并持续正常的'read()'阻塞。 (这可能是因为调用进程没有其他操作,所以这很自然。)对于'O_NONBLOCK',初始读取将返回'-EWOULDBLOCK'直到数据可用;还支持'SIGIO'和轮询。 LDD3书中详细描述了所有这些。 –

+0

哪个湿度计传感器?你可以发布你的完整代码(github等)吗?最近我一直在写这么多类型的代码,并且很好奇。 – stevieb

回答

0

在open方法中对传感器使用工作队列或其他异步基元进行必要的采样。在工作函数中,使用wait_queue通知poll可以读取设备。

在打开的方法

work_function() 
{ 
    /*perform the necessary sampling*/ 
    /*after done, use wait queue to notify poll the device is readable.*/ 
} 
DECLARE_WORK(name, work_function, data); 

static int open(struct inode *inode, struct file *filp) 
{ 
    /*do other stuff....*/ 
    queue_work(.......); 
} 

static unsigned int scull_p_poll(struct file *filp, poll_table *wait) 
{ 
    poll_wait(filp, &dev->outq, wait); 
    ....... 
    return mask; 
} 

LDD第7章将很有帮助。

+0

所以你说的是我开始测量。如果在读取之前打开之后有很长的等待时间,我可能会收到过时的数据。 – doron

+0

实际上,poll也会使进程等待,它只能监视多个fd,怎么样才能在poll中开始测量呢? SIGIO可能是一个更好的解决方案@doron –

+0

在民意调查中启动流程有其优点,唯一突出的问题是如何处理陈旧的数据。 – doron