在Linux中的/ dev / tty设备上处理用户中断(UART中断)

时间:2022-12-11 20:54:40

Here is some code sample, but the issue is that the signal handler is not called when a 'break' is sent over the serial line with 'putty'.

下面是一些代码示例,但问题是当使用'putty'通过串行线发送'break'时,不会调用信号处理程序。

#include <sys/ioctl.h>
#include <termios.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>

void signal_handler(int status);

int main(void)
{
    FILE* f = fopen("/dev/ttyS0", "r+b");

    struct sigaction saio; /* definition of signal action */
    saio.sa_handler = signal_handler;
    // saio.sa_mask = 0;
    saio.sa_flags = 0;
    saio.sa_restorer = NULL;
    sigaction(SIGINT,&saio,NULL);

    struct termios options;

    tcgetattr (fileno(f), &options);

    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);

    options.c_iflag &= ~IGNBRK; // & ~IGNPAR;
    options.c_iflag |= BRKINT; // | PARMRK | INPCK;
    options.c_cc[VMIN] = 0;
    options.c_cc[VTIME] = 1;

    if (tcsetattr(fileno(f), TCSAFLUSH, &options) == -1)
    {
        printf("port setup failure\n");
        return -1;
    }

    ioctl(fileno(f), TIOCSCTTY, (char *)NULL);
    while (1) {
        int ch = fgetc(f);
        switch (ch) {
        case EOF: break;
        case EAGAIN: printf("[EAGAIN]"); break;
        case EBADF: printf("[EBADF]"); break;
        case EINTR: printf("[EINTR]"); break;
        case EIO: printf("[EIO]"); break;
        case EOVERFLOW: printf("[EOVERFLOW]"); break;
        default:
            if (isprint(ch))
                putchar(ch);
            else
                printf("[%02x]", ch);
        }
    }
}

void signal_handler(int status)
{
    printf("received SIGINT %d signal.\n", status);
    exit(0);
}

Here are my stty settings:

这是我的stty设置:

user@dev:~/$ sudo stty -F /dev/ttyS0
speed 9600 baud; line = 0;
intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = <undef>; start = <undef>; stop = <undef>; susp = <undef>; rprnt = <undef>; werase = <undef>;
lnext = <undef>; flush = <undef>; min = 0; time = 1;
-imaxbel
-opost -onlcr
-icanon -iexten -echo -echoe -echok -echoctl -echoke

What am I missing / why do I not receive a signal? I'm using a USB-2-Serial converter and I can see that the break is sent over, but nothing is triggered at all on this client end.

我错过了什么/为什么我没有收到信号?我正在使用USB-2-Serial转换器,我可以看到中断发送,但在此客户端端根本没有触发任何内容。

1 个解决方案

#1


Give it a try under strace supervision. Add a call to tcgetattr after your tcsetattr and check that all the changes you asked for were made
You should also get rid of your controlling tty before acquiring a new one. According to man tty-ioctl :

在strace监督下试一试。在你的tcsetattr之后添加对tcgetattr的调用,并检查你要求的所有更改是否已经完成你还应该在获取一个新的控件之前删除你的控制tty。根据man tty-ioctl:

   Controlling tty
       TIOCSCTTY int arg
              Make  the given tty the controlling tty of the calling process.  The calling process must be a session leader and not have a controlling tty already.  If
              this tty is already the controlling tty of a different session group then the ioctl fails with EPERM, unless the caller is root  and  arg  equals  1,  in
              which case the tty is stolen, and all processes that had it as controlling tty lose it.

       TIOCNOTTY void
              If  the  given tty was the controlling tty of the calling process, give up this controlling tty.  If the process was session leader, then send SIGHUP and
              SIGCONT to the foreground process group and all processes in the current session lose their controlling tty.

#1


Give it a try under strace supervision. Add a call to tcgetattr after your tcsetattr and check that all the changes you asked for were made
You should also get rid of your controlling tty before acquiring a new one. According to man tty-ioctl :

在strace监督下试一试。在你的tcsetattr之后添加对tcgetattr的调用,并检查你要求的所有更改是否已经完成你还应该在获取一个新的控件之前删除你的控制tty。根据man tty-ioctl:

   Controlling tty
       TIOCSCTTY int arg
              Make  the given tty the controlling tty of the calling process.  The calling process must be a session leader and not have a controlling tty already.  If
              this tty is already the controlling tty of a different session group then the ioctl fails with EPERM, unless the caller is root  and  arg  equals  1,  in
              which case the tty is stolen, and all processes that had it as controlling tty lose it.

       TIOCNOTTY void
              If  the  given tty was the controlling tty of the calling process, give up this controlling tty.  If the process was session leader, then send SIGHUP and
              SIGCONT to the foreground process group and all processes in the current session lose their controlling tty.