はじめに
どうも。こんにちは。
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 ~)
