我正在尝试接收串行数据,但是我无法确定时间。
当接收到串行数据时,什么时候SIGIO触发-在接收到数据的第一个字节时,或者当接收到特定字符(CR,NL ...)时?
设置串行数据端口:
/* Open serial port.
* O_RDONLY - Only receive data
* O_NOCTTY - Leave process control to other 'jobs' for better portability.
* O_NDELAY - Enable non-blocking read
*/
fd = open(PORT_PATHNAME, O_RDONLY | O_NOCTTY | O_NDELAY);
fd = open(PORT_PATHNAME, O_RDONLY | O_NOCTTY | O_NDELAY);
/* Set process ID, that will receive SIGIO signals for file desc. events */
fcntl (fd, F_SETOWN, getpid());
/* Enable generation of signals */
fcntl (fd, F_SETFL, O_ASYNC);
...
options.c_oflag &= ~OPOST;
/* Set terminal options using the file descriptor */
tcsetattr(fd, TCSANOW, &options);
struct termios options;
tcgetattr(fd, &options);
/* Set baudrate */
options.c_cflag = B115200;
设置信号中断:
/* Add UART handler function */
saio.sa_handler = signal_handler_IO;
/* Non-zero used for calling sighandler on alternative stacks and so on */
saio.sa_flags = 0;
/* Not specified by POSIX -> not in use */
saio.sa_restorer = NULL;
/* Bind SIGIO (async I/O signals) to the defined structure */
int status = sigaction(SIGIO, &saio, NULL);
答案 0 :(得分:0)
SIGIO应该在您获得一字节数据后立即触发。
这是在具有驱动程序ftdi_sio
的Linux上测试的最低示例:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <signal.h>
#include <termios.h>
#include <unistd.h>
#define tty "/dev/ttyUSB0"
#define baudrate B9600
void byteCallback(int status); // interrupt function
int main(){
int ttyDev = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (!ttyDev)
{
printf("couldn't open serial device");
return -1;
}
struct sigaction byteAction; // set the serial interrupt handler
struct termios oldtio, newtio;
//create signal handler
byteAction.sa_handler = byteCallback;
sigemptyset(&byteAction.sa_mask); //sa_mask = 0
byteAction.sa_flags = SA_RESTART;
sigaction(SIGIO, &byteAction, NULL);
//Allow process to detect SIGIO
fcntl(ttyDev, F_SETOWN, getpid());
fcntl(ttyDev, F_SETFL, FASYNC);
tcgetattr(ttyDev, &oldtio); //backup current settings
newtio.c_cflag = baudrate | CS8 | CLOCAL | CREAD;
newtio.c_cflag &= ~CRTSCTS; //disable hw flow control
newtio.c_iflag &= ~(IXON | IXOFF | IXANY); //disable flow control
newtio.c_iflag |= IGNPAR; //ignore parity
newtio.c_oflag = 0;
newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //raw mode
newtio.c_cc[VMIN] = 1;
newtio.c_cc[VTIME] = 0;
tcflush(ttyDev, TCIFLUSH);
tcsetattr(ttyDev, TCSANOW, &newtio);
while(1){
//Wait for SIGIO to fire
}
}
void byteCallback(int status){
printf("SIGIO fired!\r\n");
}
另请参阅this question
答案 1 :(得分:0)
SIGIO
被解雇以宣布您可以接收字符。...(这意味着,如果您进行read(2)
的系统调用,您将收到一些东西),这意味着将没有信号如果您尝试读取但没有任何数据可供读取,则触发该事件。正如您将在下面阅读的,这并不意味着您的系统未接收到任何字符,这取决于串行线路的配置方式。继续阅读...
您的问题非常有趣,因为只有在驾驶员认为您可以读取更多数据时才发送信号,这可能是:
当您按返回键时,如果终端处于规范模式(烹饪或行模式),则在不馈入数据行(或按^D
字符)之前,您不会使输入缓冲区对应用程序可用。
当您以原始模式收到VMIN
个字符时(如果VMIN
的设置与0
不同)
当VTIME
收到至少VMIN
个字符后(设置VMIN
等于零后)过去了
SIGIO
的原因是不必等待字符到达,因此可以在信号处理程序中对其进行处理。但是,这没有什么用,因为中断本质上是异步的,您将不得不将这些字符(可能在进行了一些可能的异步处理之后)放入某种缓冲区中。有select(2)
或poll(2)
系统调用,可让您在一组输入通道之间进行选择,并在有某些输入可用时立即唤醒。
因此,总而言之,答案是:这取决于。
这取决于驱动程序的构建方式,配置方式以及使用的设备类型。 SIGIO
绝对与硬件中断无关,该硬件中断可能会以这种中断的形式传递给进程,并且它如何依赖于某些因素。
这样思考::如果您进行read(2)
阻止操作,则您会在某个时刻被唤醒,因为有可用数据并且您能够接收到一些数据。如果您已配置为接收SIGIO
,则由于某些数据可用而唤醒您的过程也将触发SIGIO
。这里没有魔术,这就是过程....如果是因为您的read(2)
不再等待而唤醒您的驱动程序,则该驱动程序将向您发送信号,但前提是您决定不忽略它