永続性

情報システム概論 I 

                                       筑波大学 システム情報工学研究科 
                                       コンピュータサイエンス専攻, 電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/compsys1-2007/2008-02-14
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/

■復習

プログラミング言語で記述しているのは、主記憶(メインメモリ)の内容を書 き換えること。内容を書き換えられるのは、主記憶だけ。

■目標

ファイルとデータベースの役割を理解する。永続性という考え方を理解する。

Unix Super Text 上巻「第9章 ファイルとディレクトリ」、「第21章 ファイル とディレクトリの高度な操作」、「第23章 アクセス制御」、下巻「第45章 記 憶媒体」参考。

■記憶のためのハードウェア

◆記憶の持続性からみた時の記憶ハードウェア分類

速度、容量以外の性質。
揮発的 (volatile)
電源を切ると消えてしまう。メインメモリとして使われるRAM(Random Access Memory)など。
永続的 (persistent)、不揮発的 (non volatile)
電源を切っても残っている。ハード・ディスク、{CD,DVD}-{ROM,R,RW,RAM}、USBフラッシュメモリ・ディスクなど。
仮想記憶は、揮発的なメモリの「容量」を事実上拡大したもの。 キャッシュ・メモリは、RAMの「速度」を、高速化したもの。

永続的なメモリを仮想化して使いやすくしたものが、 ファイルやデータベース。

プロセス、オペレーティング・システム、ファイル・システム、デバイス・ドライバ、ディスク

図? ディスクとファイル

■ファイル

ハードディスク、CD-ROM、USB フラッシュメモリ等の永続的な記憶媒体をオペ レーティング・システムの働きにより仮想化して使いやすくしたもの。 ファイルには、名前がある。名前を保存いるための特殊なファイルを、「ディ レクトリ(directory)」という。「フォルダ(folder)」ということもある。

もしも、ファイルに名前がつけられなかったら・・・・。

◆ディレクトリの木構造

ファイルに名前を付ける方法としては、木構造に基づくものが主流。

◆ファイルがどう見えるか

◆ストリーム

もともとは、流れの意味。通信でよくつかう。 プログラムから見た時、ファイルを先頭のバイトから順にアクセスする方法が ある。
FOPEN(3)                 BSD Library Functions Manual                 FOPEN(3)

NAME
     fopen, fdopen, freopen -- stream open functions

LIBRARY
     Standard C Library (libc, -lc)

SYNOPSIS
     #include <stdio.h>

     FILE *
     fopen(const char * restrict path, const char * restrict mode);

     FILE *
     fdopen(int fildes, const char *mode);

     FILE *
     freopen(const char *path, const char *mode, FILE *stream);

DESCRIPTION
     The fopen() function opens the file whose name is the string pointed to
     by path and associates a stream with it.
なぜ、先頭から順にアクセスするのか。 ストリームといっても、早送り、巻戻しくらいはできるものもある。fseek(), lseek()。

磁気テープ、ヘッド固定

図? 磁気テープ

◆ランダムアクセス

ハードディスクは、セクタの集まり。 1セクタは、512バイト程度の大きさ。 先頭から順ではなくても、セクタの番号を指定すれば、どんな順番でもアクセ スできる。 (アクセスするのに、3つの番号(面の番号、シリンダ番号、シリンダ内のセ クタ番号)を個別に指定する必要があるディスクもあった。)

セクタ、シリンダ、アーム、ヘッド

図? ハードディスクの構造

ハードディスク上に作られたファイルは、(テープ上に作られたファイルと違っ て)、先頭から順にアクセスだけでなく、メインメモリと同様に、任意の順番 に配列のようにアクセスすることができる。

API

■プログラミング言語から見た永続性

基本的には、プログラミング言語は、メインメモリ(揮発的なメモリ)しかあ つかえない。 永続性なメモリを扱いたい時には、ファイル入出力を通じて扱うことになる。

◆変数

プログラミング言語で、メインメモリを抽象化したもの。

◆変数の寿命とスコープ

プログラミング言語の変数には、スコープと寿命がある。
スコープ
空間的な概念。 プログラムの字面上、どの範囲から使えるか。 プログラムで、スコープにない変数をアクセスするとコンパイル時にエラーに なる。
寿命
時間的な概念。 「いつ」、その変数がアクセス可能になり、「いつ」、アクセスできなく なるのか。実行時のタイミング。 無効になった変数を無理やり使うと、何が起るかわからない。(C言語では、 ポインタを通じて、無効になった変数をアクセスできてしまうことがある。)
int x;

f()
{
    int y ;
    static int z ;
}
種類 スコープ 寿命
外部変数 全プログラム プログラムの実行開始から終了まで
普通の局所変数 関数内 その関数の実行中とそこから別の関数を呼んでいる間
staticな局所変数 関数内 プログラムの実行開始から終了まで
static変数(関数の外に定義) 同一ファイル内 プログラムの実行開始から終了まで
(C言語にはない) (いろいろ) プログラムの終了後も残る
C言語でプログラムの終了後も残る変数を実現するには、システム・コールやラ イブラリで明示的にファイル入出力を行う必要がある。

◆counter-mem.c

メモリ中にある変数(大域変数)の内容を増やす。 ファイル入出力は行わない。

[counter-mem.c]

   1:	/*
   2:	        counter-mem.c -- print the counter value in memory.
   3:	*/
   4:	#include <stdio.h>
   5:	
   6:	int counter = 0;
   7:	
   8:	main( int argc, char *argv[], char *envp[] )
   9:	{
  10:	        printf("%d -> ",counter );
  11:	        counter = counter + 1 ;
  12:	        printf("%d\n",counter );
  13:	}
実行例:
% make counter-mem [←]
cc     counter-mem.c   -o counter-mem
% ./counter-mem  [←]
0 -> 1
% ./counter-mem [←]
0 -> 1
% ./counter-mem [←]
0 -> 1
% []
何度実行しても、0 から始まる。

◆counter-file.c

ファイル入出力を行う。

[counter-file.c]

   1:	/*
   2:	        counter-file.c -- print the counter value in a file.
   3:	*/
   4:	#include <stdio.h>
   5:	
   6:	static void load_counter();
   7:	static void save_counter();
   8:	
   9:	int counter = 0;
  10:	
  11:	main( int argc, char *argv[], char *envp[] )
  12:	{
  13:	        load_counter();
  14:	        printf("%d -> ",counter );
  15:	        counter = counter + 1 ;
  16:	        printf("%d\n",counter );
  17:	        save_counter();
  18:	}
  19:	
  20:	#include <unistd.h>     /* pread() */
  21:	#include <fcntl.h>      /* open() */
  22:	#include <stdlib.h>     /* exit() */
  23:	
  24:	#define FILENAME "counter.data"
  25:	
  26:	static void
  27:	load_counter()
  28:	{
  29:	    int fd ;
  30:	        fd = open(FILENAME,O_RDWR|O_CREAT,0666);
  31:	        if( fd < 0 )
  32:	        {
  33:	            perror(FILENAME);
  34:	            exit(1);
  35:	        }
  36:	        read( fd, &counter, sizeof(counter) );
  37:	        close( fd );
  38:	}
  39:	
  40:	static void
  41:	save_counter()
  42:	{
  43:	    int fd ;
  44:	        fd = open(FILENAME,O_RDWR|O_CREAT,0666);
  45:	        if( fd < 0 )
  46:	        {
  47:	            perror(FILENAME);
  48:	            exit(1);
  49:	        }
  50:	        write( fd, &counter, sizeof(counter) );
  51:	        close( fd );
  52:	}
実行例:
% make counter-file [←]
cc     counter-file.c   -o counter-file
% ls -l counter.data [←]
ls: counter.data: No such file or directory
% ./counter-file  [←]
0 -> 1
% ls -l counter.data [←]
-rw-r--r--   1 yas  prof  4 Feb 13 18:40 counter.data
% ./counter-file [←]
1 -> 2
% ./counter-file [←]
2 -> 3
% ./counter-file [←]
3 -> 4
% []
実行する度に、カウンタの値が増える。最初に実行した時に、ファイル "counter.data"が作られる。大きさは、4 バイト。int 型の大きさと同 じ。

◆配列

プログラミング言語で、メインメモリを抽象化したもの。連続した番地におか れた一様なデータ。
もの 指すもの 内容
メインメモリ 番地(数) バイト単位
配列 添字(index)(数) 任意のデータ単位

◆連想配列(associative array)

添字として、(文字列など)数以外のものが使える。 数でも、連続ではなくて、粗(sparse)なものが使える。

例:Rubyの連想配列。「{}」で空の連想配列が作られる。その後は、普通の配 列と同様に代入できる。

[ruby-assoc.rb]

#!/usr/bin/ruby

aa = {};
aa["apple"] = 100;
aa["orange"] = 120;
printf("apple == %d\n", aa["apple"] );
printf("orange == %d\n", aa["orange"] );
実行例:
% ./ruby-assoc.rb [←]
apple == 100
orange == 120
% []
連想配列のことを、プログラミング言語によっては、ハッシュ表(Hash table) ということもある。
キー (key)
表を検索する時に使うもの。配列の添字相当。
値 (value)
検索の結果得られるもの。
連想配列には含まれていないデータを検索すると、「見つからない」という 結果がかえってくる。

◆連想メモリ

ハードウェアでも、(番地を入れたら値が出てくるのではなく)値を入れると 別の値が出てくる少容量のメモリ(連想メモリ)が使われる。

◆ファイルを連想配列として考える

ファイルには名前がある。 ファイル名を入れると、内容が得られる連想配列として考えることができる。

◆人間を連想配列として考える

単なる連想配列だと、人間はコンピュータにはるかに劣る。

◆永続的な変数

C言語で記述できるのは、寿命がいくら長くても、プログラムの実行開始から 終了まで。

C言語にはないが、プログラムの実行開始前にも有効で、終了後にも有効な変 数を考えてみる。これを永続的な変数という。

プログラミング言語で永続的な変数を支援しているものがある。

一般の言語からは、ライブラリ関数で「永続的なハッシュ表(連想配列)」と して扱うことが多い。

◆永続的なハッシュ表を扱うライブラリ

DB は、Database の略だが、情報学類でこれらをデータベースと呼ぶと怒られ る。固有名詞として扱うと安全。

◆永続的なハッシュ表を扱うライブラリ(Ruby DBM)

Ruby では、DBM というライブラリを使うと、 NDBM (Berkeley DB) をハッシュ表のように扱える。 ただし、キーもデータも文字列。(文字列を入れると文字列がかえって来る。)

保存するプログラム [ruby-dbm-store.rb]

#!/usr/bin/ruby

require 'dbm';
db = DBM::open("fruits",0666);
db["apple"] = 100;
db["orange"] = 120;
db.close();
保存されたデータを利用するプログラム [ruby-dbm-print.rb]
#!/usr/bin/ruby

require 'dbm';
db = DBM::open("fruits");
printf("%d\n", db["apple"] );
db.close();
実行例:
% ls fruits.db [←]
ls: fruits.db: No such file or directory
% ./ruby-dbm-store.rb [←]
% ls fruits.db [←]
fruits.db
% file fruits.db [←]
fruits.db: Berkeley DB (Hash, version 7, native byte-order)
% ./ruby-dbm-print.rb  [←]
100
% []

■データベース

複数の応用目的で共有を意図して組織的かつ永続的に格納されたデータ群。

ファイルと同様に、 永続的な記憶媒体を 仮想化して使いやすくしたもの。

ファイルと違い

データベースは、データベース管理システム(DBMS, DataBase Management System)の働きにより作られる。

◆データモデル

DBMSが提供する、対象データとそれに対する操作を規定した共通の枠組み。 例

◆関係データベース

関係データモデルに基づいて作られたデータベース。

「関係」とは、2次元の表。 関係データモデルでは、表の集合としてデータベースを構築する。
サークル
サークル名 部屋番号 電話番号
テニス 101 1011
サッカー 203 4423
社員
社員番号 氏名 基本給与 住所
001 筑波太郎 400 つくば市×××
002 土浦次郎 450 土浦市△△△
003 水戸三郎 450 水戸市○○○
所属
サークル名 社員番号 役職
テニス 001 代表
テニス 002 会計
サッカー 001 一般部員
サッカー 003 幹事

◆関係データベースに対する操作

◆問い合わせ言語

データベースに対して、一般ユーザが操作しやすいように設計された言語。

◆SQL

関係データベースに対する、標準化された問い合わせ言語。 例:データベースの定義(create table)、データの挿入(insert)、検索(select)
% sqlite3 company1.db [←]
SQLite version 3.1.3
Enter ".help" for instructions
sqlite> create table circles( name char(20), room char(3), phone char(4));[←]
sqlite> insert into circles values('ukouken', '123', '4444');[←]
sqlite> select * from circles where room='123';[←]
ukouken|123|4444
sqlite> .quit[←]
% ls -l company1.db  [←]
-rw-r--r--   1 yas  prof  2048 Feb 15 16:36 company1.db
% []
挿入したデータは、消す(delete)まで使える。
% sqlite3 company1.db  [←]
SQLite version 3.1.3
Enter ".help" for instructions
sqlite> select * from circles where phone='4444';[←]
ukouken|123|4444
sqlite> .quit
% []

■ファイルとセキュリティ

◆アクセス制御

アクセス制御(access control) とは、「主体」が、「オブジェクト」を「操作」する時、どんな操作なら正し いということを定義して、それがきちんと守られていることをということを保 証することである。

図? アクセス制御における主体、オブジェクト、および、操作

図? アクセス制御における主体、オブジェクト、および、操作

◆Unixにおけるアクセス制御とは

Unixでは、アクセス制御の主体は、プロセスである。 アクセス制御のオブジェクトは、ファイル、または、プロセスである。 操作には、次のようなものがある。

◆ファイルに対するアクセス制御

UNIXでは、ファイルの「内容」のアクセス制御を次の3段階で行う。
ユーザ
ファイルのUID(所有者)が、プロセスのUIDと同じ
グループ
ファイルのGIDが、プロセスのGIDのリストのどれかと同じ
その他
上の2つに当てはまらない時
これをつかって、モード属性の下位9ビットのうち、どの3ビットを使うかを 決める。そして、そのビットが1になっていれば、その操作が許される。

ファイルの「内容」のアクセス3段階であるが、ファイルの「属性」次の2段 階である。

ユーザ
ファイルのUID(所有者)が、プロセスのUIDと同じ
それ以外
ファイルのUID(所有者)が、プロセスのUIDと異なる
ユーザの権限では、ファイルの属性(モード、グループ、時刻)を変更する ことができる。それ以外の権 限では、属性を読み出すことはできるが、変更は一切できない。 つまり、ファイルの内容がアクセスできなくても、ls -l, stat(2) で 属性を調べることはでる。

◆プロセスに対するアクセス制御

プロセスのアクセス制御は、次の2段階で行なう。
同一ユーザ
操作対象のプロセスが、操作するプロセスのUIDと一致している。
それ以外
操作対象のプロセスが、操作するプロセスのUIDと一致していない。
プロセスの操作としては、シグナルを送ることができるかどうか (kill() システムコール) と、デバッガで デバッグすることができるとか(ptrace() システムコール)、トレースを調べることができるかなどが ある。それらの操作は、同一ユーザの場合 許され、そうではない場合は、許されない。

◆データベースに対するアクセス制御

ファイルと類似のものの他に、次のようなものがある。

■関連科目

ファイル入出力については、3年生の専門科目「システムプログラム」で学ぶ。 ファイル・システムの実装方法については、 「オペレーティングシステム I」で学ぶ。 データベースについては、「データベース概論 I」「データベース概論 II」、 「情報検索概論I」で学ぶ。
Last updated: 2008/02/14 18:37:03
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>