へっぽこ社会人4年生がプログラミングを頑張る

へっぽこ社会人4年目がプログラミング系統を中心に書きたいことをつらつらと書きます

システムコールで遊んでみる その2

前回readwriteについて書きました。 今回はopencloseについて、簡単に書いていこうと思います。 まだ自分自身も勉強途中なので、ちゃんとは説明出来ないんですけどね...

以下は引数に指定したファイルをオープンして標準出力に表示するプログラムです。

#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv)
{
  int fd;
  ssize_t size;
  char buf[1024];

  if(argc != 2) {
    write(STDERR_FILENO, "Error\n", 6);
    return 1;
  }
  fd = open(argv[1], O_RDONLY);
  if(fd == -1) {
    write(STDERR_FILENO, "Error\n", 6);
    return 1;
  }

  size = read(fd, buf, sizeof(buf));
  write(STDOUT_FILENO, buf, size);
  close(fd);
  
  return 0;
}
ちょっと解説(っぽいもの)

システムコールopenを利用するにはfcntl.hを、closeを利用するにはunistd.hをインクルードする必要があります。 openの戻り値は非負整数のファイルディスクリプタを、失敗なら-1を返します。 closeは成功で0、失敗で-1を返します。

opencloseのインタフェースは以下の通り。

  • open
  • int open(const char *path, int flag, ...);
  • close
  • int close(int fd);

openの第1引数pathはファイル名を指定します。 第2引数flagはファイルの状態を示すフラグ(後述)を指定します。 closeの第1引数fd閉じるファイルディスクリプタを指定します。

openでは読み書きのためにファイルを開いたり作成したりします。 んで、引数flagに、ファイルを開く(あるいは作成する)時に、状態を指定します。 O_RDONLY読み込み専用で開く、O_WRONLY書き込み専用で開く、O_CREATファイルが存在しなければ作成する、といったように 今回の場合、コマンド引数から指定したファイルを読み込みたいので、 O_RDONLYを利用します。

ファイルの内容を読み込むわけですが、 開いているファイルから内容をbufに読み込むのにreadを利用します。 前回と異なる点は、openの第1引数にfdを指定して、ファイルの中身をbufに読み込んでいる点です。 bufに取り込んだら、あとは前回のwriteと同じです。 最後に、ファイルを閉じるために、closeに開いたファイルのディスクリプタfdを渡します。

詳しくは、man 2 openman 2 closeとターミナルに入力してマニュアルを呼び出してみてください。

そういえば、前回、標準入力と標準出力のファイルディスクリプタのマクロを紹介しましたが、今回はエラー処理の出力に標準エラーのファイルディスクリプタを指定しました。 標準エラーのファイルディスクリプタは2なのですが、これもSTDERR_FILENOというマクロが定義されています。

とりあえず、今回はここまで。 次はlseekを触ってみようかなと考えてますが、まだしっかりとは考えてないです...