UNIXプログラミング

【C言語】低レベル入出力関数(open, close, read, write, lseek)とは?

みなさんこんにちは!

今回はUNIXプログラミングを行うときに、

ぜひ覚えておきたい低レベル入出力関数についてまとめていきます。

低レベル入出力関数っていったい何?

低レベル入出力関数とは名前の通り、

標準入出力ライブラリの関数などと比較したときに相対的に低レベルな入出力関数のことを言います。

つまり標準入出力関数ライブラリの関数などは、この低レベル入出力関数を用いて実装されているわけです。

主な特徴としては、

・システムコールによって入出力の操作をする

・読んだデータはヌル終端しない

・標準入出力関数と違ってバッファリングはしない

などが挙げられます。

みなさんはファイルの入出力を行うとき、基本的にfopen()を使っていると思うのですが

大雑把に言えばfopen()の中ではopen()を使ってファイルの入出力をして、

それに加えてバッファリングなどの高速で処置をするための工夫を付け加えているのです。

主な低レベル入出力関数の種類と解説

低レベル入出力関数にはopen()をはじめとして、

書き込むための関数や読み込むための関数が存在します。

open()

open()はファイル入出力の準備をするための関数です。

使い方は以下のようになります。

返り値:ファイル記述子

<引数>

・path: 操作したいファイルのパス

・flags: O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNCの論理和

・mode: ファイルのアクセス許可レベル(chmodで設定しているアレ)

ファイル記述子とはファイルへの参照を抽象化したキーのことで、

ファイルを識別するための使われます。

close()

close()とはファイル記述子をクローズする関数です。

使い方は以下のようになります。

返り値: 成功した場合は0、 エラーが発生した場合は-1。

<引数>

・ファイル記述子

close()のエラー処理は省略されがちですが、本当はチェックした方が良いです

read()

read()とはファイルを読み込むための関数です。

使い方は以下のようになります。

返り値: 読み込んだバイト数、 エラーが起きた時は-1を返す

<引数>

・fd: ファイル記述子

・buf: バッファの先頭を指すポインタ

・nbytes: 読み込むバイト数(符号なし整数)

while文などのループでread()を使い、

nbytesが返り値より大きくなったら、全て読み込んだことを示します。

read()を実行する際に用意したバッファより読み込むバイト数が大きい場合ループをすることになりますが

カーネルがどこまで読み込んだかを記憶してくれる(カレントファイルオフセット)ので、特別な操作をする必要がありません。

write()

write()はファイルを書き込む関数です。

使い方は以下のようになります。

返り値: 書き込んだバイト数、エラーが起きた時は-1を返す

<引数>

・fd: ファイル記述子

・buf: バッファの先頭を指すポインタ

・nbytes: 書き込むバイト数(符号なし整数)

write()もread()と同様で、

カーネルがどこまで読み込んだかを記憶してくれるので、特別な操作をする必要がありません。

エラー処理について

当然のことなのですが、

低レベル入出力関数を使用するときにもエラー処理をしっかりとするようにしましょう。

エラー処理をするためには以下の二つを使います。

errno

システムコールでエラーが起きた時には、errnoにエラーコードが入ります。

perror()

errnoの内容に応じて標準エラー出力にエラーを表示します。

引数は任意の文字列を入れることで、どこでどんなエラーが起きたのかを分かるようにできます。