C 非规范(raw)模式下的异步串行通信和在linux/osx中生成SIGIO

C 非规范(raw)模式下的异步串行通信和在linux/osx中生成SIGIO,c,asynchronous,serial-port,signal-handling,C,Asynchronous,Serial Port,Signal Handling,首先,当数据准备好读取时,我很难让串行设备生成SIGIO 我正在尝试编写一个简单的串行接口,使用usb到串行适配器与micro通信。我想保持这个接口与micro中的接口类似(中断驱动,使用回调),因此我决定采用捕获SIGIO信号的方式,而不是使用单独的线程或恒定的非阻塞串行读取。以下是我的初始化代码(在各种异步串行教程中,大部分代码看起来都很熟悉): 字节回调是我的信号处理程序。我已经通过手动向进程发送信号来验证它是否有效。与我通信的micro不支持任何类型的流量控制,因此已禁用。我已经通过使用

首先,当数据准备好读取时,我很难让串行设备生成SIGIO

我正在尝试编写一个简单的串行接口,使用usb到串行适配器与micro通信。我想保持这个接口与micro中的接口类似(中断驱动,使用回调),因此我决定采用捕获SIGIO信号的方式,而不是使用单独的线程或恒定的非阻塞串行读取。以下是我的初始化代码(在各种异步串行教程中,大部分代码看起来都很熟悉):

字节回调是我的信号处理程序。我已经通过手动向进程发送信号来验证它是否有效。与我通信的micro不支持任何类型的流量控制,因此已禁用。我已经通过使用标准读/写系统调用验证了我可以从设备读写

问题是当数据进入时,信号处理程序不会被调用。我怀疑这是因为只有在接收到CR或行尾字符时才会生成SIGIO。由于这是完全原始模式,并且没有发送这样的字符,因此不会生成SIGIO。目前,我只在OSX上尝试过这一点,但理想情况下,相同的代码也可以在linux上运行

任何帮助都将不胜感激。我搜索了很多次,人们总是建议只使用select()或其他方法。这几乎成了一个挑战,我还没有准备好放弃


谢谢。

SIGIO的生成肯定与CR/NL无关。您的问题是,在设置
FASYNC
标志后,您立即清除了它:

fcntl(ttyDev, F_SETFL, FASYNC); //make async
fcntl(ttyDev, F_SETFL, FNDELAY);  //non blocking reads AND CLEAR FASYNC FLAG
你应该做的是:

fcntl(ttyDev, F_SETFL, O_ASYNC|O_NONBLOCK);
或者最好(为了避免清除可能已经设置的任何其他标志):


注意,我还冒昧地用相应的标准名称替换了您使用的奇怪的非标准标志名称。:-)

我的回答应该可以解决您的问题,但请注意,将信号用于异步IO是一个非常糟糕的主意。如果您想知道它有多错,Emacs会这样做。:-)不开玩笑的是,它不好的主要原因是,在大多数情况下,您在可以调用的函数以及可以从信号处理程序中执行的操作方面受到了极大的限制。违反规则似乎是可行的,但它会有危险的竞争条件,这将导致程序死锁或崩溃的情况非常罕见(当然,这种情况很少见,很难再现或调试)。使用SIGPOLL代替SIGIO也是一个问题。通常
SIGPOLL
SIGIO
都是一样的,但无论如何,这些都是不可携带的垃圾。。当然,即使它们不一样,这些信号的默认操作是终止进程,因此OP会注意到生成的信号。:-)啊,我忘了把信号换回SIGIO。我在玩弄它,看看我做错了什么。回答的人:谢谢。这可能正是正在发生的事情。今晚我要试试这些变化。
fcntl(ttyDev, F_SETFL, O_ASYNC|O_NONBLOCK);
fcntl(ttyDev, F_SETFL, O_ASYNC|O_NONBLOCK|fcntl(ttyDev, F_GETFL));