「プログラムの入出力」の版間の差分

提供: C言語入門
移動: 案内検索
(ページの作成:「Unixのプロセスは、プロセスが起動されるときに、OSによって3つのファイル記述子(file descriptor)が用意されます。それらは、特...」)
(相違点なし)

2014年5月14日 (水) 23:13時点における版

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

入出力で使用されるアンバッファドなシステムコール

  • open
  • close
  • read
  • write
  • lseek

標準入力から標準出力へコピーするだけのプログラム 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

関連項目

  1. プログラムの入出力