SIGIO什么时候解雇?

时间:2019-07-02 06:37:18

标签: c linux

我正在尝试接收串行数据,但是我无法确定时间。

当接收到串行数据时,什么时候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);

2 个答案:

答案 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)不再等待而唤醒您的驱动程序,则该驱动程序将向您发送信号,但前提是您决定不忽略它

相关问题