【发布时间】:2011-02-22 19:28:23
【问题描述】:
根据我在 The Open Group 网站上阅读的 fcntl、open、read 和 write,我的印象是 O_NONBLOCK 是否设置在文件描述符上,因此非阻塞 I/O 是否与描述符一起使用,应该是该文件描述符的属性,而不是底层文件的属性。作为文件描述符的一个属性意味着,例如,如果我复制一个文件描述符或打开另一个描述符到同一个文件,那么我可以将阻塞 I/O 与另一个一起使用,而将非阻塞 I/O 与另一个一起使用。
但是,在使用 FIFO 进行实验时,似乎不可能同时将阻塞 I/O 描述符和非阻塞 I/O 描述符添加到 FIFO(因此是否设置了 O_NONBLOCK 是底层文件[FIFO]):
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int fds[2];
if (pipe(fds) == -1) {
fprintf(stderr, "`pipe` failed.\n");
return EXIT_FAILURE;
}
int fd0_dup = dup(fds[0]);
if (fd0_dup <= STDERR_FILENO) {
fprintf(stderr, "Failed to duplicate the read end\n");
return EXIT_FAILURE;
}
if (fds[0] == fd0_dup) {
fprintf(stderr, "`fds[0]` should not equal `fd0_dup`.\n");
return EXIT_FAILURE;
}
if ((fcntl(fds[0], F_GETFL) & O_NONBLOCK)) {
fprintf(stderr, "`fds[0]` should not have `O_NONBLOCK` set.\n");
return EXIT_FAILURE;
}
if (fcntl(fd0_dup, F_SETFL, fcntl(fd0_dup, F_GETFL) | O_NONBLOCK) == -1) {
fprintf(stderr, "Failed to set `O_NONBLOCK` on `fd0_dup`\n");
return EXIT_FAILURE;
}
if ((fcntl(fds[0], F_GETFL) & O_NONBLOCK)) {
fprintf(stderr, "`fds[0]` should still have `O_NONBLOCK` unset.\n");
return EXIT_FAILURE; // RETURNS HERE
}
char buf[1];
if (read(fd0_dup, buf, 1) != -1) {
fprintf(stderr, "Expected `read` on `fd0_dup` to fail immediately\n");
return EXIT_FAILURE;
}
else if (errno != EAGAIN) {
fprintf(stderr, "Expected `errno` to be `EAGAIN`\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
这让我想:是否有可能对同一个文件有一个非阻塞 I/O 描述符和阻塞 I/O 描述符,如果是,它是否取决于文件的类型(常规文件、FIFO、块特殊文件、字符特殊文件、套接字等)?
【问题讨论】:
-
我想知道这一点,因为如果设置的 O_NONBLOCK 是底层文件的属性,那么调用打开带有 O_NONBLOCK not 在 oflags 中设置的文件的调用可能 仍然返回带有 O_NONBLOCK 标志的文件描述符。
标签: c nonblocking file-descriptor fcntl posix-api