「プログラムの入出力」の版間の差分
提供: C言語入門
(ページの作成:「Unixのプロセスは、プロセスが起動されるときに、OSによって3つのファイル記述子(file descriptor)が用意されます。それらは、特...」) |
|||
行42: | 行42: | ||
|} | |} | ||
== 入出力で使用されるアンバッファドなシステムコール == | == 入出力で使用されるアンバッファドなシステムコール == | ||
− | + | リードとライトで用いる関数は、以下の通りです。 | |
− | + | ||
* read | * read | ||
* write | * write | ||
+ | |||
+ | ファイルのオープンとクローズとシークで用いる関数は、以下の通りです。 | ||
+ | * open | ||
+ | * close | ||
* lseek | * lseek | ||
+ | |||
+ | === read === | ||
+ | <syntaxhighlight lang="c"> | ||
+ | #include <sys/types.h> | ||
+ | #include <unistd.h> | ||
+ | |||
+ | ssize_t | ||
+ | read(int fd, void *buf, size_t nbytes); | ||
+ | |||
+ | #include <sys/uio.h> | ||
+ | |||
+ | ssize_t | ||
+ | readv(int fd, const struct iovec *iov, int iovcnt); | ||
+ | </syntaxhighlight> | ||
+ | === write === | ||
+ | <syntaxhighlight lang="c"> | ||
+ | #include <sys/types.h> | ||
+ | #include <unistd.h> | ||
+ | |||
+ | ssize_t | ||
+ | write(int fd, const void *buf, size_t nbytes); | ||
+ | |||
+ | #include <sys/uio.h> | ||
+ | |||
+ | ssize_t | ||
+ | writev(int fd, const struct iovec *iov, int iovcnt); | ||
+ | |||
+ | struct iovec { | ||
+ | void *iov_base; /* Base address. */ | ||
+ | size_t iov_len; /* Length. */ | ||
+ | }; | ||
+ | </syntaxhighlight> | ||
== 標準入力から標準出力へコピーするだけのプログラム stdin2stdout.c == | == 標準入力から標準出力へコピーするだけのプログラム stdin2stdout.c == |
2014年5月14日 (水) 23:18時点における最新版
Unixのプロセスは、プロセスが起動されるときに、OSによって3つのファイル記述子(file descriptor)が用意されます。それらは、特別なことをしなければ、端末に紐付けられます。その3つのファイル記述子は、標準入力(stdin)、標準出力(stdout)、標準エラー出力(stderr)です。
読み方
- file descriptor
- ファイルディスクリプタ
目次
概要
Unixのプロセスは、プロセスが起動されるときに、OSによって3つのファイル記述子(file descriptor)が用意されます。それらは、特別なことをしなければ、端末に紐付けられます。その3つのファイル記述子は、標準入力(stdin)、標準出力(stdout)、標準エラー出力(stderr)です。 ls を実行すると、3つの入出力は、その端末に接続されます。
$ ls
ファイル記述子は、正の整数です。0からはじまります。プロセスがファイルをオープンするとOSがファイルをオープンし、それに新たにファイル記述子を割り当てます。
リダイレクトした場合、標準出力は、list.txt に接続されます。シェルがシステムコールを利用して、ファイルをオープンし、実行するプログラム(ls)の標準出力をlist.txtのファイル記述子に変更し、lsを実行します。
$ ls > list.txt
ファイル記述子とマクロ
ファイル記述子の番号 | 入出力 | unistd.hで定義されるマクロ | ファイルポインタ |
---|---|---|---|
0 | 標準入力 | STDIN_FILENO | stdin |
1 | 標準出力 | STDOUT_FILENO | stdout |
2 | 標準エラー出力 | STDERR_FILENO | stderr |
入出力で使用されるアンバッファドなシステムコール
リードとライトで用いる関数は、以下の通りです。
- read
- write
ファイルのオープンとクローズとシークで用いる関数は、以下の通りです。
- open
- close
- lseek
read
#include <sys/types.h> #include <unistd.h> ssize_t read(int fd, void *buf, size_t nbytes); #include <sys/uio.h> ssize_t readv(int fd, const struct iovec *iov, int iovcnt);
write
#include <sys/types.h> #include <unistd.h> ssize_t write(int fd, const void *buf, size_t nbytes); #include <sys/uio.h> ssize_t writev(int fd, const struct iovec *iov, int iovcnt); struct iovec { void *iov_base; /* Base address. */ size_t iov_len; /* Length. */ };
標準入力から標準出力へコピーするだけのプログラム stdin2stdout.c
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include <err.h> const ssize_t BUF_SIZE = 8192; int main(int argc, char *argv[]) { ssize_t n; char buf[BUF_SIZE]; for(;;){ n = read(STDIN_FILENO, buf, BUF_SIZE); if (0 == n) { break; } else if (-1 == n) { err(EXIT_FAILURE, "read error"); } ssize_t r = write(STDOUT_FILENO, buf, n); if (r != n) { err(EXIT_FAILURE, "write error: size=%lu, write=%lu", n, r); } } exit(EXIT_SUCCESS); }
コンパイルは、以下の通りです。
$ cc stdin2stdout.c
stdin2stdout.c の解説
- 入力の終端に達すると read は、 0 を返します。
- read は、エラーの場合、-1 を返します。
- write は、書き込めたバイト数を返します。
- あまり大きなバイト数は、一度に書き込めないかもしれません。
- ソケットプログラミングでは、一度にwriteできないことがあります。
- writeは、エラーの場合、-1を返します。
アンバッファドなシステムコールの利用
システムコール read/writeは、アンバッファドな関数です。バッファリングのないシステムコールを使う場合には、プログラマは、システムの効率のためにバッファサイズやシステムコールの呼び出しを注意するべきです。
バッファリングなし | バッファリングあり |
---|---|
write,writev | fwrite, fputs, fprintf, printf |
read,readv | fread, fgets, fscanf, scanf |
関連項目
- プログラムの入出力