我一直在阅读关于 EINTR
等的 write(2)
,并试图确定我是否需要在我的程序中检查它。作为健全性检查,我试图编写一个会遇到它的程序。程序永远循环,反复写入文件。
然后,在一个单独的 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 状态(进程代码 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)