関数仕様
書式
1 2 3 4 |
#include <unistd.h> ssize_t write(int fd, void *buf, size_t count); |
引数
fd | 書き込み先ファイルを指すファイルディスクリプタ(ファイル記述子) |
buf | 書き込むデータを格納しているバッファの先頭アドレス |
count | 書き込むバイト数 |
戻り値
0以上の値 | 書き込んだバイト数 |
-1 | エラーが発生(errno にエラー番号がセットされています) |
代表的なエラー(errno)
- EAGAIN
fd がソケットや PIPE 以外を指していて O_NONBLOCK が設定されており、
書き込みを行うと停止する状況にある - EPIPE
fd がソケットか PIPE に接続されており、その反対側(読み込み側)が既にクローズ(close)されている
これが発生した場合は、書き込みを行なうプロセスは SIGPIPE シグナル (signal)も受ける - EINTR
指定されたバイト数を書き込み完了するまでにシグナルに割り込まれた
機能
- ファイル記述子 fd が示すファイルに、buf に格納されたのデータを最大 count バイト書き込みます
- fd が seek に対応しているファイルを指している場合、write は現在のファイルオフセットから開始されます。ファイルオフセットは書き込んだバイト数分だけインクリメントされます
- write は read とは異なり、戻り値が示す書き込んだバイト数が countで指定したバイト数よりも小さくなることは殆どありません
注意すること
注意ポイント
書き込んだ内容がすぐにディスク(HDD/SSD)や外部ストレージに反映されるわけではない
write で書き込んだ内容は、カーネルのバッファ(ディスクキャッシュ)へ 格納されます。
カーネルが暇な時に実際に書き込まれます。書き込んだ後に読み出しても、 参照先はカーネルのバッファになるため、実際に書き込まれたかどうかを 確認するのは困難です。
また、バッファにデータが滞留している間に電源を OFF にすると、ファイルが壊れます。
参考
ファイルの破損を防ぐ書き込み方は、「ファイル破損を防ぐ方法」にまとめています。
サンプル:エラーの対処と最後まで書き出す細工
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 54 55 56 57 58 59 60 61 62 |
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <stdio.h> #include <string.h> #define LOG_FILE_PATH "./log.dat" static ssize_t my_write (int fd, void *buf, size_t count) { ssize_t size = 0; char *buffer = buf; char *endp = buf + count; while (buffer < endp) { size = write(fd, buffer, endp - buffer); if (size < 0) { if (errno == EINTR) { continue; } else if (errno == EAGAIN) { sleep(1); continue; } else { return -1; } } buffer += size; } return count; } int main (void) { int fd, size; char buf[128]; fd = open(LOG_FILE_PATH, (O_RDWR | O_CREAT), 0664); if (fd < 0) { return -1; } sprintf(buf, "Hello world!!"); /* Force write 128 bytes */ size = my_write(fd, buf, sizeof (buf)); if (size != sizeof(buf)) { close(fd); return -1; } if (fsync(fd) < 0) { close(fd); return -1; } close(fd); return 0; } |