c - 为什么 write(2) 不返回 EINTR?

标签 c linux

我一直在阅读关于write(2) 等的EINTR,并试图确定我是否需要在我的程序中检查它。作为完整性检查,我尝试编写一个会遇到它的程序。程序永远循环,重复写入文件。

然后,在一个单独的 shell 中,我运行:

while true; do pkill -HUP test; done

但是,我从 test.c 看到的唯一输出是来自信号处理程序的 .。为什么 SIGHUP 不会导致 write(2) 失败?

测试.c:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>

void hup_handler(int sig)
{
    printf(".");
    fflush(stdout);
}

int main()
{
    struct sigaction act;
    act.sa_handler = hup_handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);

    sigaction(SIGHUP, &act, NULL);

    int fd = open("testfile", O_WRONLY);

    char* buf = malloc(1024*1024*128);

    for (;;)
    {
        if (lseek(fd, 0, SEEK_SET) == -1)
        {
            printf("lseek failed: %s\n", strerror(errno));
        }
        if (write(fd, buf, sizeof(buf)) != sizeof(buf))
        {
            printf("write failed: %s\n", strerror(errno));
        }
    }
}

最佳答案

Linux 倾向于避免 EINTR 对文件的写入/读取;见discussion here .当进程阻塞磁盘写入时,它可能被放置在 uninterruptible sleep 中。 state (process code D) 表示此时不可中断。这取决于设备驱动程序; online copy of Linux Device Drivers, 3rd Edition是一个很好的引用,从内核方面来看这是如何出现的。

对于其他行为可能不同的平台,或者对于肯定会发生 EINTR 的管道和套接字,您仍然需要处理 EINTR。

请注意,您一次只写入 sizeof(void *) 个字节:

char* buf = malloc(1024*1024*128);

    if (write(fd, buf, sizeof(buf)) != sizeof(buf))

应该是

const size_t BUF_SIZE = 1024*1024*128;
char* buf = malloc(BUF_SIZE);

    if (write(fd, buf, BUF_SIZE) != BUF_SIZE)

关于c - 为什么 write(2) 不返回 EINTR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11844284/

相关文章:

c - 反对 free_if_heap(void *ptr)?

linux - 联机帮助页中 Unix 命令名称后括号中的数字是什么意思?

linux - 在同一命令中使用 mapfile 和 awk

php - 使用php远程连接到mysql服务器

linux - putty - 需要最近的标准输出

c - 链接器不通知多个定义

c - MPI 和 C : loop through file of commands in file

c - 使用互斥体在 C 中实现的第一个读写器解决方案有什么问题?

c++ - 关于 C 和 C++ 之间公共(public)头文件的预处理器保护

php - 通过 php 在 gammu 中打开设备时出错