是否将O_NONBLOCK设置为文件描述符或基础文件的属性?
从我一直在阅读上由The Open Group网站上fcntl
,open
,read
和write
,我得到的印象是,是否O_NONBLOCK
被设置在一个文件描述符,因此无论是非阻塞I/O是用来与描述符应该是该文件描述符的属性,而不是底层文件。作为文件描述符装置的属性,例如,如果我复制一个文件描述符或打开另一个描述符到相同的文件,然后我可以使用阻塞I/O与一个并且与其它非阻塞I/O。是否将O_NONBLOCK设置为文件描述符或基础文件的属性?
与FIFO进行实验,但是,看来,它不可能同时具有阻塞I/O描述符和非阻塞I/O描述符的FIFO(因此无论O_NONBLOCK
设置是底层的一个属性文件[先进先出]):
#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是打开的文件的描述的性质,而不是文件描述符的,也不是底层文件的。
是的,你可能有单独的文件描述符打开同一个文件,其中之一是阻塞,另一个是非阻塞的。
您需要区分FIFO(使用mkfifo()
创建)和管道(使用pipe()
创建)。
注意的阻断状态是“打开文件的描述”的属性,但在简单的情况下,有文件描述符和打开文件描述之间的一个一对一的映射。 open()
函数调用将创建一个新的打开的文件描述和一个新的文件描述符,用于引用打开的文件描述。
当您使用dup()
,你有两个文件描述符共享一个打开文件的描述,和属性都属于开放文件描述。 fcntl()
的说明表示F_SETFL影响与文件描述符关联的打开文件描述。需要注意的是lseek()
调整与文件描述符关联的打开文件描述的文件中的位置 - 所以它影响从原来的1个重复的其他文件描述符。
删除该错误代码处理,以减少它,你必须:
int fds[2];
pipe(fds);
int fd0_dup = dup(fds[0]);
fcntl(fd0_dup, F_SETFL, fcntl(fd0_dup, F_GETFL) | O_NONBLOCK);
现在无论fd0_dup和FDS [0]参见(因为dup()
)相同的开放文件描述,所以fcntl()
操作影响两个文件描述符。
if ((fcntl(fds[0], F_GETFL) & O_NONBLOCK)) { ... }
因此,这里观察到的行为是POSIX所要求的。
哦,好的。所以“文件描述符”和“文件描述”是有区别的。两个文件描述符可以共享相同的文件描述,并且这些标志是描述的属性。再次查看文档以打开文档,它表示该函数“将创建一个打开的文件描述”。 我认为我现在明白了。 – 2010-05-22 22:35:14
是的,你明白了。 – 2011-08-14 19:47:46
@DanielTrebbien:一些标志属于文件描述符,例如'FD_CLOEXEC'。 – jfs 2015-02-12 16:57:50
我很想知道这件事,因为如果O_NONBLOCK被设置为底层文件的属性,那么打开带有O_NONBLOCK *的文件的一个调用*不在* oflags *中设置*然而可能会返回带有O_NONBLOCK标志的文件描述符。 – 2010-05-22 22:06:52