関数仕様
書式
|
1 2 3 4 |
#include <unistd.h> ssize_t read (int fd, void *buf, size_t count); |
引数
| fd | 読み出すデータが格納されているファイルディスクリプタ(ファイル記述子) |
| buf | 読み出したデータを格納するバッファの先頭アドレス |
| count | 読み込む最大バイト数 |
戻り値
| 正の値 | 読み込んだバイト数 |
| 0 | ファイルオフセットが既にEOF |
| -1 | エラーが発生 (errno にエラー番号がセットされています) |
代表的なエラー (errno)
- EAGAIN
fd がソケットや PIPE 以外を指していて O_NONBLOCK が設定されており、読み込みを行うと停止する状態にある - EBADF
fd が有効なファイルディスクリプターでないか、読み込みのために オープン (open) されていない - EINTR
指定されたバイト数を読み込み完了するまでにシグナルに割り込まれた
機能
- ファイルディスクリプター fd から最大 count バイトをアドレス buf で始まるバッファーへ読み込む
- fd が seek に対応しているファイルを指している場合、read は現在のファイルオフセットから開始される。ファイルオフセットは読み込んだバイト数分だけインクリメントされる
- 現在のファイルオフセットがファイル末尾の場合は、読み出しは行われず 0 を返す
- count が SSIZE_MAX より大きい場合、動作は保証されない
注意すること
注意ポイント①
read 関数は、引数 count で指定したバイト数を必ず読み込んでくれるわけではない。
例えば、read 処理中に signal などの割り込みが発生した場合、 read は途中で中断されます。
これらのケアを正しく行わないと、中途半端なデータを処理してしまってプログラムが破綻してしまう。
注意ポイント②
ソケットなどにアクセスする場合は、届いているデータを最後まで読み出す必要があります。
カーネル側のバッファが溢れ、書き込む側でエラーが発生します。
サンプル:エラーの対処と最後まで読みだす細工
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #define LOG_FILE_PATH "./test.log" static ssize_t my_read (int fd, char *buf, size_t size) { ssize_t done = 0; size_t s = size; while (s > 0) { done = read (fd, (void *)buf, s); if (done < 0) { if (errno == EINTR) /* Interrupt */ continue; else /* Error */ return done; } else if (done == 0) { /* EOF */ return size - s; } else { buf += done; s -= done; } } return size; } int main (void) { int fd, size; char buf[128]; fd = open (LOG_FILE_PATH, O_RDONLY); if (fd < 0) return -1; size = my_read (fd, buf, sizeof (buf)); if (size != sizeof (buf)) { close (fd); return -1; } /* 処理を書く */ close (fd); return 0; } |