SIGQUIT 和 STDIN(读取函数的意外转储)
SIGQUIT and STDIN (unexpected dump of read function)
我在处理 stdin 和 sigquit 信号时遇到了问题。任务是忽略 sigquit 信号。一切都很好,除了所有 'read' 缓冲区都消失了,我不知道如何避免它。这是我的代码:
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <strings.h>
int main(void)
{
char buffer[4096];
int byte;
bzero(buffer, 4096);
signal(SIGQUIT, SIG_IGN);
while ((byte = read(0, &buffer, 4096)))
{
if (strlen(buffer) == 5 && !strncmp(buffer, "exit", 4))
break ;
write(1, "STDOUT | ", strlen("STDOUT | "));
write(1, buffer, strlen(buffer));
bzero(buffer, 4096);
}
write(1, "Program is finished\n", strlen("Program is finished\n"));
return (0);
}
这是我的输出:
$ ./test
hello world
STDOUT | hello world
hello world^\
STDOUT |
The way it should be
STDOUT | The way it should be
And how it is now^\
STDOUT |
i need help
STDOUT | i need help
really^\
STDOUT |
exit
Program is finished
OS:MacOS 莫哈韦沙漠 - 10.14.6
Clang 版本:11.0.1
这不是您的代码中的错误。您正确地忽略了 SIGQUIT,并且您的读写循环大部分都很好(我看到的唯一实际 bug 是您正在分配 return 值 read
到错误类型的变量,然后没有给予足够的重视;但这不是你眼前问题的原因)。
发生的事情是,当您键入 ^\ 时,tty 驱动程序会生成一个 SIGQUIT 并且还会丢弃任何未决的输入行 .此行为由 POSIX 指定,但只是暗示:NOFLSH
本地模式标志的定义读取
If NOFLSH is set, the normal flush of the input and output queues associated with the INTR, QUIT, and SUSP characters shall not be done.
(开放组基础规范第 7 期,2018 年版,§11.2.5 Local Modes。)
因此,如果 NOFLSH 未设置,这是默认设置,那么在处理 ^ 时,输入和输出队列都将被刷新(内容被丢弃) C、^\ 和 ^Z.
您可以使用 tcsetattr
设置 NOFLSH 标志,但您必须注意在退出时再次取消设置。我建议使用 readline
or curses
库,而不是尝试自己处理低级 tty API。
当您点击 ^C
(intr)、^Z
(susp) 和 ^\
(quit) 时,您的 tty 层正在刷新您的输入。
解决方案是在 运行 你的程序之前调用 stty noflsh
。
如果您需要以编程方式执行此操作,请参阅此 termios
manual page
中的 NOFLSH
标志
我在处理 stdin 和 sigquit 信号时遇到了问题。任务是忽略 sigquit 信号。一切都很好,除了所有 'read' 缓冲区都消失了,我不知道如何避免它。这是我的代码:
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <strings.h>
int main(void)
{
char buffer[4096];
int byte;
bzero(buffer, 4096);
signal(SIGQUIT, SIG_IGN);
while ((byte = read(0, &buffer, 4096)))
{
if (strlen(buffer) == 5 && !strncmp(buffer, "exit", 4))
break ;
write(1, "STDOUT | ", strlen("STDOUT | "));
write(1, buffer, strlen(buffer));
bzero(buffer, 4096);
}
write(1, "Program is finished\n", strlen("Program is finished\n"));
return (0);
}
这是我的输出:
$ ./test
hello world
STDOUT | hello world
hello world^\
STDOUT |
The way it should be
STDOUT | The way it should be
And how it is now^\
STDOUT |
i need help
STDOUT | i need help
really^\
STDOUT |
exit
Program is finished
OS:MacOS 莫哈韦沙漠 - 10.14.6 Clang 版本:11.0.1
这不是您的代码中的错误。您正确地忽略了 SIGQUIT,并且您的读写循环大部分都很好(我看到的唯一实际 bug 是您正在分配 return 值 read
到错误类型的变量,然后没有给予足够的重视;但这不是你眼前问题的原因)。
发生的事情是,当您键入 ^\ 时,tty 驱动程序会生成一个 SIGQUIT 并且还会丢弃任何未决的输入行 .此行为由 POSIX 指定,但只是暗示:NOFLSH
本地模式标志的定义读取
If NOFLSH is set, the normal flush of the input and output queues associated with the INTR, QUIT, and SUSP characters shall not be done.
(开放组基础规范第 7 期,2018 年版,§11.2.5 Local Modes。)
因此,如果 NOFLSH 未设置,这是默认设置,那么在处理 ^ 时,输入和输出队列都将被刷新(内容被丢弃) C、^\ 和 ^Z.
您可以使用 tcsetattr
设置 NOFLSH 标志,但您必须注意在退出时再次取消设置。我建议使用 readline
or curses
库,而不是尝试自己处理低级 tty API。
当您点击 ^C
(intr)、^Z
(susp) 和 ^\
(quit) 时,您的 tty 层正在刷新您的输入。
解决方案是在 运行 你的程序之前调用 stty noflsh
。
如果您需要以编程方式执行此操作,请参阅此 termios
manual page
NOFLSH
标志