首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SIGINT部分写入

SIGINT部分写入
EN

Stack Overflow用户
提问于 2019-09-04 07:07:49
回答 1查看 94关注 0票数 1

我有一个write_full,它应该将缓冲区完全写入标准输出,即使它被信号中断了。

我有一个循环,它使write_full保持一个字符串,直到信号处理程序更改quit为止。下面是代码:

代码语言:javascript
复制
#include <signal.h>
#include <unistd.h>
#include <errno.h>

volatile sig_atomic_t quit = 0;

void sigint_handler(int s)
{
    quit = 1;
}

int write_full(char *buf, size_t len)
{
    while (len > 0) {
        ssize_t written = write(STDOUT_FILENO, buf, len);
        if (written == -1) {
            if (errno == EINTR) { 
                continue; 
            }
            return -1;
        }
        buf += written;
        len -= (size_t)written;
    }
    return 0;
}

int main(void)
{
    struct sigaction act = {
        .sa_handler = sigint_handler
    };
    sigaction(SIGINT, &act, NULL);

    while (!quit) {
        write_full("loop\n", 5);
    }

    write_full("cleanup", 7);

    return 0;
}

我希望程序在打印“清除”之前完全编写“循环”,但我看到这样的输出:

循环播放 循环播放 循环播放 l^C 清理

为什么会发生这种情况?我希望是这样的:

循环播放 循环播放 循环播放 l^Coop 清理

因为write_full应该继续编写"oop\n“部分,即使在第一次写入是由于中断导致的短写之后。我在信号处理程序上放置了一个断点,并且逐步执行,似乎write正在报告它已经编写了4个字符,即使它只在stdout上写了"l“。因此,它不再写"oop\n“,而是只写"\n”。

代码语言:javascript
复制
l^C
Program received signal SIGINT, Interrupt.

Breakpoint 1, sigint_handler (s=2) at src/main.c:9
9           quit = 1;
(gdb) next
10      }
(gdb) next
write_full (buf=0x4020a0 "loop\n", len=5) at src/main.c:16
16              if (written == -1) {
(gdb) print written
$1 = 4

为什么会发生这种情况?我怎么才能解决这个问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-09-04 07:44:55

Ctrl会破坏终端输出。程序编写了它应该写的所有内容,但是默认情况下,终端驱动程序在Ctrl之后切断了行。这并不在你的程序控制之下。当驱动程序在将完整的行缓冲区复制到物理设备的过程中看到Ctrl时,就会发生剪切。输入行缓冲区也被丢弃。这也适用于其他信号生成字符。

stty(1)termios(3)手册页面中对此进行了相当简短的描述。

可以使用stty noflsh命令禁用此行为。

您还可以重定向到文件,以查看完整的输出。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57783184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档