システムプログラミング 第7回、8回 ファイルシステム関連の...

22
シシシシシシシシシシシ シシ シ シ 7、8 シシシシシシシシシシシ シシシシシシシ シシシシシ シシ シ

Upload: vivi

Post on 06-Feb-2016

38 views

Category:

Documents


0 download

DESCRIPTION

システムプログラミング 第7回、8回 ファイルシステム関連の システムコール. 情報工学科 篠埜 功. ディレクトリファイル. ディレクトリファイルには、ファイル名から i ノード番号 ( i ノードは index node の略 ) への 対応がファイルの数だけ格納されている。(実際のデータ構造は、ハッシュテーブルや線形リストなど。) ファイルの i ノード番号は $ ls – li 等、 ls に - i オプションを与えると確認できる。. ファイルシステムの実装. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

システムプログラミング第7回、8回

ファイルシステム関連のシステムコール情報工学科 篠埜 功

Page 2: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

ディレクトリファイルディレクトリファイルには、ファイル名からi ノード番号 (i ノードは index node の略 ) への対応がファイルの数だけ格納されている。(実際のデータ構造は、ハッシュテーブルや線形リストなど。)

ファイルの i ノード番号は $ ls –li等、 ls に -i オプションを与えると確認できる。

Page 3: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

ファイルシステムの実装ファイルシステムは、ブートブロック、スーパーブロック、 i ノードリスト、データブロックの4つの領域から構成される。• ブートブロック --- OS を起動するためのプログラムを格納。• スーパーブロック --- ファイルシステムの大きさ、ブロック数、ブロックサイズ、空きブロック、 iノードリストの大きさ、空き i ノードリストの情報などを格納。• i ノードリスト --- i ノードのリスト。 i ノードには各ファイルの種類、所有者、 permission 、変更時刻、ファイルサイズ、データブロック内の場所などが格納されている。• データブロック --- ファイルの中身が格納されている。

Page 4: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

open システムコールファイルからのデータの読み込み、ファイルへのデータの書き込みをするには、まずファイルをオープンする。これを行うのが open システムコールである。

open システムコールを使う場合、 types.h, stat.h, fcntl.h をインクルードする。

Page 5: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

open システムコールの引数

open システムコールは、パス名、フラグの2引数あるいは、これらにモードを加えた3引数で呼び出す。パス名で指定されたファイルを、フラグに従ってオープンし、ファイル記述子 (file descriptor, int 型 )を返す。フラグが O_CREAT の場合、モードが必要。ファイル記述子は、利用者ファイル記述子表の何番目かを表す。オープンするとは、データ入出力用のバッファを確保し、利用者ファイル記述子表中の1つの構造体を割り当て、構造体の各メンバーに初期値を設定することをいう。利用者ファイル記述子表については dup システムコールの説明時に説明する。

Page 6: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

open システムコールの代表的なフラグ

O_RDONLY --- 読みだしのみO_WRONLY --- 書き込みのみO_RDWR --- 読み出し、書き込みの両方を行うO_CREAT --- ファイルが存在しない場合作成する。第3引数のモードでファイルの permission 等を設定する。

これらのフラグは fcntl.h に記述されているので、インクルードして使う。

Page 7: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

モードopen システムコールの第3引数に与えられるモードでは、ファイルの permission およびセットユーザ ID ビット、セットグループ ID ビット、sticky ビット (/tmp などで使用 ) を 12 桁の2進数で表す。代表的な数値は stat.h でマクロとして提供されているが、数値で直接指定してよい。

(例) S_IRWXU --- 所有者は read, write, executeができる。その他にもあるが、 $ man –S 2 openで確認。

Page 8: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

read システムコールファイルからデータを読み出すためのシステムコールが read システムコールである。unistd.h をインクルードする。

ファイル記述子、データ格納領域へのポインタ、読み出しバイト数を引数に与える。返り値は読み出したバイト数。これが 0 のときはファイルの最後まで読み終わっているということになる。read システムコールが正常終了しなかった場合は -1 が返ってくる。このときは perror でエラーメッセージを表示する。

Page 9: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

write システムコールファイルへデータを書き込むためのシステムコールが write システムコールである。unistd.h をインクルードする。

ファイル記述子、書き込むデータが格納されている領域へのポインタ、書き込みバイト数を引数に与える。返り値は書きこんだバイト数。write システムコールが正常終了しなかった場合は -1 が返ってくる。このときは perror でエラーメッセージを表示する。

Page 10: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

close システムコールclose システムは、ファイル記述子を引数に受け取り、そのファイルをクローズする。クローズするとは、入出力用バッファを解放し、利用者記述子表内の構造体を解放することをいう。(同時に開けるファイル数に制限があるので、閉じるのがよい。閉じなければプロセス終了時に閉じられる。)

Page 11: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

例 1 :テキストファイルの先頭に a を書き込む

#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main (void) { int fd, n; char c = 'a'; if ((fd = open ("test", O_WRONLY)) == -1) { perror ("open"); exit(1); }

/* 続き */if (write (fd, &c, 1) != 1){ perror ("write"); exit(1); } if (close (fd) == -1) { perror ("close"); exit(1); } return 0;}

Page 12: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

演習課題2• テキストファイル(ファイル名は test な

ど)の先頭文字を読み取り、その文字を2文字目に書きこむ。 Open システムコールの第2引数(フラグ)は O_RDWR にする。

read, write システムコールを呼ぶたびに、読み書きのためのポインタ (kernel 内部のポインタ ) が1つ進むので、 read で読み取ったあとに write で書き込めば、 2 文字目に書きこまれることになる。

Page 13: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

例 2/* テキストファイル全部表示 */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>int main (int argc, char * argv []) { int fd, n; char c; if (argc!=2) { fprintf (stderr, "Usage: %s filename\n", argv[0]); exit(1); }

/* 続き */ if ((fd = open (argv[1],O_RDONLY)) == -1) { perror ("open"); exit(1); } while ((n = read (fd, &c, 1) ) > 0) printf ("%c", c); if (n==-1) { perror ("read"); exit(1); } if (close (fd) == -1) { perror ("close"); exit(1); } return 0;}

Page 14: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

複数バイトずつ読み込む read システムコールで、複数バイト単位で読み込むこともできる。read システムコールの返り値は、 (1) 正の場合、読み込んだバイト数を表す。 (2) 0 の場合、ファイルの内容を既に全部読み終わっていたことを表す。 (3) -1 の場合、システムコールが何らかの理由で正常終了しなかったことを表す。この場合はライブラリ関数 perror でエラー内容を表示するべき。

例えば、ファイルサイズ 260 バイトのファイルを 100 バイト単位で読み込むと、最後の回は 60バイト(返り値も 60 )になり、その後は返り値は 0 となる。

Page 15: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

例 3/* テキストファイル全部表示 */#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main (int argc, char * argv []) { int fd, n; char c[100]; if (argc!=2) { fprintf (stderr, "Usage: %s filename\n", argv[0]); exit(1); }

/* 続き */if ((fd = open (argv[1], O_RDONLY)) == -1) { perror ("open"); exit(1); } while ((n = read (fd, c, 100) ) > 0) if (write (1, c, n) != n) { perror ("write"); exit(1); }; if (n == -1) { perror ("read"); exit(1); } if (close (fd) == -1) { perror ("close"); exit(1); } return 0;}

1 は標準出力

Page 16: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

例 4/* 標準入力を標準出力へ書きだす */#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>int main (int argc, char * argv []) { int fd, n; char c[100]; while ((n = read (0, c, 100) ) > 0) if (write (1, c, n) != n) { perror ("write"); exit(1); };

/* 続き */ if (n == -1) { perror ("read"); exit(1); } return 0;}

1 は標準出力0 は標準入力

Page 17: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

新しいファイルの作成

新しいファイルの作成は、 open システムコールの第2引数のフラグに O_CREAT を指定する。(ファイルが存在していたらそのファイルを使う。存在しなければファイルを新しく作る。)

他のフラグと組み合わせて指定できる。組み合わせるときはビットの or 演算子 | を用いる。

例えば、 write only で開きたい場合は、 openシステムコールの第2引数に O_WRONLY | O_CREATを指定する。さらに、存在しているときに内容を消したいときは O_TRUNC をさらに追加で指定する。

Page 18: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

例 5/* 入力をファイルへ書きだす*/#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <stdlib.h>int main (int argc, char * argv []) { int fd, n; char c[100]; if (argc!=2) { fprintf (stderr, "Usage: %s filename\n", argv[0]); exit(1); }

/* 続き */if ((fd = open (argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) { perror ("open"); exit(1); } while ((n = read (0, c, 100) ) > 0) if (write (fd, c, n) != n) { perror ("write"); exit(1); }; if (n == -1) { perror ("read"); exit(1); } if (close (fd) == -1) { perror ("close"); exit(1); } return 0;}

0 は標準入力

Page 19: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

演習課題3実行ファイルの引数に2つのファイル名を受けとり、1つ目のファイル(存在するファイル)のコピーを2つ目のファイルに作成するプログラムを作成せよ。(コピーコマンド)

コピー先ファイルの open 時の引数 第2引数 --- O_WRONLY | O_CREAT | O_TRUNC 第3引数 --- 0644(8 進表記 )とせよ。これにより、コピー先のファイル名が存在していたら、内容が消去されてから書き込まれる。

Page 20: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

レポート課題3cat コマンドの以下の機能を、システムコール

(open, close, read, write) を使って実装せよ。

引数無しの場合 --- 標準入力を標準出力へコピー

引数がある場合 (1個以上のファイル名を引数にとる ) --- それらのファイルの内容を結合したものを標準出力に書き出す。

cat コマンドを使った場合と挙動を比較し、同じであることを確認したのち提出すること。

Page 21: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

レポートの提出方法□ 下記のファイルを作成し、提出• kadai3.c, kadai3.txt

□ 提出方法システムプログラミング講義用の課題提出用フォルダ内にある kadai3 というフォルダの中に自分の学籍番号を名前とするフォルダを作成し、その中に上記ファイルを置く。 kadai3.txt 内に学籍番号、氏名、日付、および作成したプログラムの簡単な説明を記載する。

□ 提出期限  12月 11日の 23:59 まで。締め切り後に提出した場合、成績への反映を保証しない。

Page 22: システムプログラミング 第7回、8回 ファイルシステム関連の システムコール

参考 : ライブラリ関数を使った場合#include <stdio.h>

void filecopy (FILE *fpin, FILE *fpout) { int c; while ((c = getc(fpin)) != EOF) putc (c, fpout);}

int main (int argc, char * argv []) { FILE *fp; if (argc==1) filecopy (stdin, stdout); else while (--argc > 0) if ((fp = fopen (*++argv, "r")) == NULL) { printf ("cat: can't open %s\n", *argv); return 1; } else { filecopy (fp, stdout); fclose (fp); } return 0;}

この実装では1バイトずつコピーしている。複数バイトまとめて読み込んで書き込んだ方が速い。