在 Linux 中处理 /dev/tty 设备上的用户中断(UART 中断)
下面是一些代码示例,但问题是当使用“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-串行转换器,我可以看到中断已发送过来,但该客户端上根本没有触发任何内容。
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'.
#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:
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在 strace 监督下尝试一下。 在
tcsetattr
之后添加对tcgetattr
的调用,并检查是否已完成您要求的所有更改在获取新的 tty 之前,您还应该摆脱您的控制 tty。 根据 man tty-ioctl :
Give it a try under strace supervision. Add a call to
tcgetattr
after yourtcsetattr
and check that all the changes you asked for were madeYou should also get rid of your controlling tty before acquiring a new one. According to man tty-ioctl :