はじめに
どうも。こんにちは。
42tokyoといったところで、ソケットプログラミング??を学んでいます。
課題で、ノンブロッキングなファイルディスクリプタを扱うことになり「ノンブロッキングI/O」について調べてみました。
間違い等があれば、ご指摘ください。
結論
「ノンブロッキングI/O」とは、ファイルディスクリプタをノンブロッキングな状態で扱うこと。
ノンブロッキングにすることで、処理効率が上がる場合がある。
「ノンブロッキングI/O」と「非同期I/O」は、異なるもの。
サンプルコード
ノンブロッキングなファイルディスクリプタからread();で読み込んでみる。
non_blocking_read.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main(void) {
// ファイルディスクリプタをノンブロッキングに設定
int flags = 0;
if ((flags = fcntl(STDIN_FILENO, F_GETFL)) == -1) {
perror("fcntl");
exit(EXIT_FAILURE);
}
flags |= O_NONBLOCK;
if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1) {
perror("fcntl");
exit(EXIT_FAILURE);
}
while (1) {
sleep(3);
// char buffer[1024] = {0};
char buffer[4] = {0};
ssize_t bytes_read = 0;
errno = 0;
// ノンブロッキングなファイルディスクリプタからデータを読み取る
bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer));
if (bytes_read == -1) {
perror("read");
if (errno == EAGAIN || errno == EWOULDBLOCK) {
continue ;
} else {
exit(EXIT_FAILURE);
}
} else if (bytes_read > 0) {
// データが読み取られた場合
printf("Read %zd bytes: %s", bytes_read, buffer);
} else {
// データがない場合
printf("No data available.\n");
break ;
}
}
return (0);
}
私の理解
- ノンブロッキングなファイルディスクリプタからの読み取り(read();)では、
bytes_read = read(STDIN_FILENO, buffer, sizeof(buffer));
で処理が止まらない。 - read();の後で、エラー処理を書く必要がある。(戻り値による条件分岐が必要。)
- errnoがEAGAIN(または、EWOULDBLOCK)のときは、処理は継続。
参考
The Linux Programming Interface
44. 9 Nonblocking I/O (P.915 ~)
44.10 Semantics of read() and write() on Pipes and FIFOs (P.917 ~)
TCP/IP ソケットプログラミング C言語編
5.3 ノンブロッキング I/O (P.82 ~)