Linuxのopen(低水準入出力)の使い方やfopenとの違いをまとめていく

調べていたら思ったよりはまってしまったので、これを機にopenに関してまとめておく。

open の基礎知識

openとは、Unixにおける入出力システムを提供してくれる関数のこと。早い話が、C言語のfopenの低レベルバージョンの関数

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

例えば、以下のように書くことで、test.txtに"hello"と書き込める。

#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>

int main() {
    int fp = open("./test.txt", O_CREAT | O_RDWR, S_IRWXU | S_IRWXO);
    char *str = "hello";
    write(fp, str, strlen(str));
    return 1;
}

openの具体的な使い方

では、openの使い方を具体的に見ていく。

int open(const char *pathname, int flags, mode_t mode);
  • 第1引数 ファイル名
  • 第2引数 ファイルへのアクセスや作成に関する設定フラグ
  • 第3引数 モード(0777みたいなやつ)

戻り値には、int型のファイルディスクリプターを返す。(ディスクリプターとは、FILE *fpみたいにファイルを識別するやつ)

int flags 第2引数について

第2引数には、必ずアクセスモードを1つ入れなければいけない。アクセスモードとは、読み込み専用とか書き込み専用とか読み書き用みたいなやつで、以下の3つが用意されている。

  • O_RDONLY
  • O_WRONLY
  • O_RDWR

他にも第2引数には、ファイル作成フラグとファイル状態フラグを追加できる。

ファイル作成フラグとは、「O_CREAT」のようにファイルが存在しなければ追加する、と言う設定ができるもの。ファイル状態フラグとは、「O_NOFOLLOW」のように、ファイルがシンボリックリンクだった場合openが失敗するようにする、などができるもの。(シンボリックリンクとは、ファイルの分身みたいなやつ)

ファイル作成フラグとファイル状態フラグの詳細については、「Man page of OPEN」が詳しい。

mode 第3引数について

第3引数は必須ではないが、例えば第2引数にO_CREATを定義してファイルが存在しない場合に新規ファイルを作成するようにした場合に、その新規ファイルのパーミッション(mode)を指定する場合に必要になる。

例えば、「S_IRWXU」と指定すると「700 ユーザー (ファイルの所有者) に読み込み、書き込み、 実行の許可」を設定できる。詳細は、「Man page of OPEN」を見ると良い。(O_CREATEの説明のちょっと下に掲載されている)

openとfopenの違いとは?

openfopenの違いを列挙すると、以下の2点があげられる。

  • fopenはOSに依存しないが、openはUnix系でしか使えない
  • fopenの方が高速に動作する

なぜfopenの方が高速に動作するかと言うと、fopenではバッファを作っており、そのバッファを通してファイルの出入力を行っているからだ。

openではファイルと直接やり取りをしているため、10回100回とopenを使うと、その分だけファイルとのやり取りが生じている。一方でfopenはバッファを作成してそのバッファが一杯になった時に、初めてファイルに入出力を行うのでopenよりも高速に動く。

ちなみに、fopenの優秀性に関しては、以下の記事で書かれている。(公式の解説ページがなかったけど)