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

标签 linux signals ioctl tty

这是一些代码示例,但问题是当使用“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);
}

这是我的 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

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

最佳答案

strace下试一试监督。在您的 tcsetattr 之后添加对 tcgetattr 的调用,并检查您要求的所有更改是否已完成
在获得新的 tty 之前,您还应该摆脱控制 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.

关于linux - 在 Linux 中处理/dev/tty 设备上的用户中断(UART 中断),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/978253/

相关文章:

c# - 优雅地杀死在 Linux 上运行的 .NET Core 守护进程

linux - 将文件复制到子目录并重命名

ruby - 如何在 Ruby 进程中捕获信号

c - 我需要在 fedora 操作系统中的 I2c 上发送原始数据缓冲区

c - 用于 OLED 屏幕的 Debian I2C 驱动程序不起作用。 [SSD1306]

c - 在 Qt-Creator SDK 上以 root 身份运行代码

c - while循环中的scanf无法输入任何内容

c++ - 跨线程发送 glib 信号

linux - Cygwin:中断阻塞读取

c - 相当于 I_PUSH 的 Linux