UNIXの入出力システムは非常にシンプルです。入出力とは単純なバイト列の 送出と受取に過ぎません。ファイル記述子と呼ばれる整数の値でファイルを区 別し、それについて入出力を行ないます。ですから非常に少ない数の関数がシ ステムコールとして用意されています。
int open( char* path, int flags[, int mode] ) ファイルを開く int close( int fd ) ファイルを閉じる int read( int fd, char* buf, int nbyte ) 読み出し int write( int fd, char* buf, int nbyte ) 書き込み int lseek( int fd, off_t offset, int whence ) 読み書き点の移動 int dup( int fd ) ファイル記述子の複製 int ioctl( int fd, int request, caddr_t arg ) 装置固有の操作
典型的な使い方は例えば次のようなものでしょう。
#include <stdio.h> #include <fcntl.h> ... int fd; /* ファイル記述子 */ int buf[512]; /* 出力バッファ */ /* 新たに出力ファイルを作る。*/ fd = open( "output.dat", O_WRONLY | O_CREAT, 0644 ); /* fdが-1ならばエラー */ while( TRUE ) { /* 適当にbufをデータで埋めて */ wc = write( fd, buf, 2048 ); } /* wcには実際書かれたバイト数がかえる。*/ close( fd ); /* ファイルを閉じる。*/
同様に入力の場合
fd = open( "input.dat", O_RDONLY ); while( TRUE ) { rc = read( fd, buf, 2048 ); if( rc == 0 ) break; /* EOF */ } close( fd );
openシステムコールの最初の引数はファイル名です。2番目の引数はフラッ グと呼ばれどのようなファイルを開くのかを表わすビットの集まりです。この 例ではO_WRONLY(書き出し専用)かつO_CREAT(新規ファイル)が指定されていま す。O_RDONLY(読み出し専用)やO_RDWR (読み書き用)、O_APPEND(ファイルの末 尾に加える)などが定義されています。man 2 openをやってみましょう。3番目 の引数はファイルに設定されるアクセスモードです。chmodコマンドで設定す るものです。今の場合0644ですから所有者の読み書きとそれ以外の読みだしを 許可しています。C言語では0で始まる数字は8進数として扱われます。openシ ステムコールはうまく行くとファイル記述子を返します。それ以外のコールは その値をfdとして使っています。ファイル記述子は整数で、プロセスごとに用 意されたファイルデータベースを参照する鍵になります。writeやreadシステ ムコールでは引数にファイル記述子、バッファのアドレス、受取/送出したい バイト数を与えます。実際に受取/送出されたバイト数が戻り値として返され ます。
lseekは読み出し書き込み位置を移動します。戻り値としてファイルの先頭 からのバイト数を返します。
lseek( fd, 2048L, SEEK_SET ); /* ファイルの先頭から2048バイト目に移動 */ lseek( fd, 0L, SEEK_END ); /* ファイルの末尾の次のバイトに移動 */
SEEK_SETやSEEK_ENDはどこから数えるかを表わしています。現在のポインター の位置を知るには、
lp = lseek( fd, 0L, SEEK_CUR );
現在位置から0バイトのところに移動して(つまり何もせず)、現在のポインター の位置を先頭から数えたバイト数で受け取ります。
それぞれのプロセスにはopenの必要のない入出力ファイルとして
標準入力(stdin) fd = 0 標準出力(stdout) fd = 1 標準エラー出力(stderr) fd = 2
が用意されています。ユーザプログラムが直接これらの記述子を指定してファ イルを開くことは出来ませんが、dupシステムコールによって他のファイルに リダイレクトすることができます。別のファイルを開いておいて、(fdとする。)
close( 0 ); /*リダイレクトのためにまず標準入力を閉じる。*/ dup( fd ); /*fdのコピーが一番数の少ないファイル記述子0に割当 */
dupはその時使える最も小さい数字をファイル記述子として利用します。この 例では直前で0が開放されているのでdupは0を採用します。これ以後記述子0を 用いた入出力はfdに対してのものになりリダイレクトされたことになります。 このことはデーモンプロセスをforkによって起動した場合などに有用です。詳 しくはプロセス間通信のところで解説します。
これらのシステムコールは処理の対象を単なるバイト列と考えています。テ キストであるか、バイナリデータであるかは意識されていません。それゆえ意 味のあるレコードとしての解釈や書式付けはすべてユーザプログラムの責任で す。DAQの入出力には当然必要になるものです。
それはあんまり大変だという場合にはより高い水準の入出力として用意され ているC言語ライブラリ関数を使うほうが便利です。完全なテキストファイル を作る場合などです。