我有两个设备通过串口相互连接。 一个作为主人,另一个作为奴隶。
主设备是基于ARM的套件,运行linux。
当前情况是主发送命令然后轮询com端口,直到从站回复。
现在我不想使用民意调查。我需要处理器执行其他任务,直到奴隶回复。
我知道解决方案是使用中断但无法找到更多细节。 我找到了一些使用信号的解决方案。它以非阻塞模式读取ttys,然后在数据就绪时发送io信号。
那么,串行通信中的中断和信号有什么区别? 在使用中断时是否正确我应该编写设备驱动程序或内核模块? 为了不使用轮询,还有其他有效的解决方案吗?
答案 0 :(得分:1)
为了不使用轮询,还有其他有效的解决方案吗?
前段时间我有同样的任务,我找到解决问题的最好方法是使用pthreads。基本上,我接下来做了:
pthread_cond_signal()
pthread_cond_wait()
函数);一旦醒来 - 从循环缓冲区读取新数据(消耗数据)并正确处理poll()
函数中提供的超时新数据。如果您不需要此功能 - 您可以在阻止模式中打开串口,只需使用阻止read()
调用(由@sawdust在评论中提出)这样你就不会浪费CPU时间等待新数据到达,同时你不需要弄乱信号(使用信号有很多complications,所以我决定避免它。)
进行异步读取的唯一其他API是来自aio_read()接口的POSIX AIO。但据我所知,aio_read()
基于信号。唯一的区别是:
SIGIO
信号告诉您新数据可供阅读,您需要手动阅读aio_read()
为您提供读取数据(仅read()
,只是异步)。我不建议你使用它,因为这个API似乎并不普及,并且没有信号驱动方法的任何好处。
那么,串行通信中的中断和信号有什么区别?
换句话说,当你的串口硬件产生中断时,它会在内核中处理,并且内核会生成SIGIO
信号,通知你的用户空间应用程序新事件(例如,新数据可供读取)。 / p>
使用中断时是否正确我应该编写设备驱动程序或内核模块?
通常是的,您只能在内核中处理中断。但在这种情况下你不需要。它已经在内核中完成,更具体地说,在line discipline代码中。它会为您生成信号(发生中断时),您可以在用户空间应用程序中使用它。
如果您需要一些细节:
tty_schedule_flip()
- > queue_work(...)
- > flush_to_ldisc()
- > receive_buf()
- > tty_ldisc_receive_buf()
- > .receive_buf2()
n_tty_receive_buf2()
- > n_tty_receive_buf_common()
- > __receive_buf()
__receive_buf()
:
if (read_cnt(ldata)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
wake_up_interruptible_poll(&tty->read_wait, POLLIN);
}
发送SIGIO
信号,如下所示:kill_fasync()
- > kill_fasync_rcu()
- > send_sigio()
- > send_sigio_to_task()
- > do_send_sig_info()
- > send_signal()
因此,当串口驱动程序中发生相应的中断时,您可以依赖内核向您发送消息(通过信号)。