o_nonblockはファイル記述子または基礎となるファイルのプロパティに設定されていますか?
-
04-10-2019 - |
質問
私がオープングループのウェブサイトで読んでいるものから fcntl
, open
, read
, 、 と write
, 、私はその印象を受けます O_NONBLOCK
ファイル記述子に設定されているため、非ブロッキングI/Oが記述子で使用されるかどうかは、基礎となるファイルではなく、そのファイル記述子のプロパティである必要があります。ファイル記述子のプロパティであることは、たとえば、ファイル記述子を複製するか、別の記述子を同じファイルに開くと、1つで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は、ファイル記述子ではなく、開くファイル説明のプロパティでも、基礎となるファイルのプロパティです。
はい、同じファイルに対して別々のファイル記述子を開くことができます。1つはブロッキングで、もう1つはブロッキングではありません。
FIFO(使用して作成されたFIFOを区別する必要があります mkfifo()
とパイプ(使用して作成されます pipe()
).
ブロッキングステータスは「オープンファイル説明」のプロパティであることに注意してくださいが、最も単純な場合、ファイル記述子とオープンファイルの説明の間に1対1のマッピングがあります。 open()
関数呼び出し新しいオープンファイル説明と、開くファイルの説明を参照する新しいファイル記述子を作成します。
使用するとき dup()
, 、2つのファイル記述子が1つのオープンファイルの説明を共有しており、プロパティはオープンファイルの説明に属します。の説明 fcntl()
F_SETFLは、ファイル記述子に関連付けられたオープンファイル説明に影響すると述べています。ご了承ください lseek()
ファイル記述子に関連付けられた開くファイル説明のファイル位置を調整します。したがって、元のファイル記述子から複製された他のファイル記述子に影響します。
コードを減らすためにエラー処理を削除すると、次のことがあります。
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で必要です。