分散システム
電子・情報工学系
新城 靖
<yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2005/2006-01-31
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
NFS ( Network File System ) は, Sun Microsystems 社が 開発したネットワーク・ファイル・システムの名前(固有名詞, 商標)。
その他のネットワーク・ファイル・システム
NFSを使うと, ネットワークを通じて別のコンピュータ上のファイルシステム
の一部分を, ローカルディスク上にあるファイルシステムと同じように, 自分
のファイルシステムの木に
マウント(mount)
できる。
図? NFSによるファイルの共有
相互に参照し合える。
nfsd というプログラムが
動いているように見える(
ps コマンドで表示される)
が、それは普通のプロセスではない。
/usr/include/rpcsvc/nfs_prot.x
表? NFSで使われているRPCの手続き
| 手続き名 | 意味 | 関連するコマンド、システムコール |
|---|---|---|
| null() | 何もしない | rpcinfo -u hostname nfs コマンド |
| getattr() | 属性の読み出し | ls -l コマンド, stat システムコール , open システムコール |
| setattr() | 属性の設定 | chmod , chown コマンド |
| lookup() | ファイルの検索 | open システムコール |
| readlink() | シンボリックリンクの読み出し | ls -l コマンド, readlink システムコール |
| read() | ファイルの読み出し | read システムコール |
| write() | ファイルの書き込み | write システムコール |
| create() | ファイルの作成 | creat システムコール, open システムコール |
| remove() | ハードリンクの削除 | rm コマンド, unlink システムコール |
| rename() | ファイル名前の変更 | mv コマンド, rename システムコール |
| link() | ハードリンクの作成 | ln コマンド, link システムコール |
| symlink() | シンボリックリンクの作成 | ln -s コマンド, symlink システムコール |
| mkdir() | ディレクトリの作成 | mkdir コマンド |
| rmdir() | ディレクトリの削除 | rmdir コマンド |
| readdir() | ディレクトリの読み出し | ls コマンド |
| statfs() | ファイルシステムの利用状況 | df コマンド, statfs システムコール |
| commit()* | ディスクへの書き込み | fsync システムコール |
| access()* | アクセス権のチェック | access システムコール |
NFS でファイルやディレクトリを区別するための識別子。32バイト。
const NFS_FHSIZE = 32;
...
/*
* File access handle
*/
struct nfs_fh {
opaque data[NFS_FHSIZE];
};
一番最初のNFSファイル・ハンドルをどうやって入手するか。
| 手続き名 | 意味 | 関連するコマンド、 システムコール |
|---|---|---|
| null() | 何もしない | rpcinfo -u hostname mount コマンド |
| mnt() | NFSファイルハンドルを返す | mount コマンド |
| dump() | マウント一覧表 | showmount hostname コマンド |
| umnt() | アンマウント | umount コマンド |
| umntall() | 全アンマウント | umount -h hostname コマンド |
| export() | アクセス可能なディレクトリのリストを返す |
2.2.5. Look Up File Name
diropres
NFSPROC_LOOKUP(diropargs) = 4;
If the reply "status" is NFS_OK, then the reply "file" and reply
"attributes" are the file handle and attributes for the file "name"
in the directory given by "dir" in the argument.
2.3.10. diropargs
struct diropargs {
fhandle dir;
filename name;
};
The "diropargs" structure is used in directory operations. The
"fhandle" "dir" is the directory in which to find the file "name".
A directory operation is one in which the directory is affected.
2.3.11. diropres
union diropres switch (stat status) {
case NFS_OK:
struct {
fhandle file;
fattr attributes;
} diropok;
default:
void;
};
The results of a directory operation are returned in a "diropres"
structure. If the call succeeded, a new file handle "file" and
the "attributes" associated with that file are returned along with
the "status".
2.2.7. Read From File
struct readargs {
fhandle file;
unsigned offset;
unsigned count;
unsigned totalcount;
};
union readres switch (stat status) {
case NFS_OK:
fattr attributes;
nfsdata data;
default:
void;
};
readres
NFSPROC_READ(readargs) = 6;
Returns up to "count" bytes of "data" from the file given by "file",
starting at "offset" bytes from the beginning of the file. The first
byte of the file is at offset zero. The file attributes after the
read takes place are returned in "attributes".
Notes: The argument "totalcount" is unused, and is removed in the
next protocol revision.
2.2.9. Write to File
struct writeargs {
fhandle file;
unsigned beginoffset;
unsigned offset;
unsigned totalcount;
nfsdata data;
};
attrstat
NFSPROC_WRITE(writeargs) = 8;
Writes "data" beginning "offset" bytes from the beginning of "file".
The first byte of the file is at offset zero. If the reply "status"
is NFS_OK, then the reply "attributes" contains the attributes of the
file after the write has completed. The write operation is atomic.
Data from this "WRITE" will not be mixed with data from another
client's "WRITE".
Notes: The arguments "beginoffset" and "totalcount" are ignored and
are removed in the next protocol revision.
2.2.2. Get File Attributes
attrstat
NFSPROC_GETATTR (fhandle) = 1;
If the reply status is NFS_OK, then the reply attributes contains the
attributes for the file given by the input fhandle.
2.3.9. attrstat
union attrstat switch (stat status) {
case NFS_OK:
fattr attributes;
default:
void;
};
The "attrstat" structure is a common procedure result. It
contains a "status" and, if the call succeeded, it also contains
the attributes of the file on which the operation was done.
2.3.5. fattr
struct fattr {
ftype type;
unsigned int mode;
unsigned int nlink;
unsigned int uid;
unsigned int gid;
unsigned int size;
unsigned int blocksize;
unsigned int rdev;
unsigned int blocks;
unsigned int fsid;
unsigned int fileid;
timeval atime;
timeval mtime;
timeval ctime;
};
...
Notes: The bits are the same as the mode bits returned by the
stat(2) system call in UNIX. The file type is specified both in
the mode bits and in the file type. This is fixed in future
versions.
The "rdev" field in the attributes structure is an operating
system specific device specifier. It will be removed and
generalized in the next revision of the protocol.
例:
ssize_t read(int fd, void *buf, size_t count); ssize_t write(int fd, const void *buf, size_t count); ssize_t pread(int fd, void *buf, size_t count, off_t offset); ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
NFS Version 2は, サーバ側で状態を保持しない(state-less)。
操作を冪等にして、サーバを無状態にすると、障害に強くなる。
RPC のようにコネクションが作られない通信サービスを使う時に冪等や無状態 といった性質を実現する時に必要になる技術。
例:NFSでのディレクトリの読み込み手続き nfsproc_readdir() で、1回の RPC で全部のデータを返せないことが起きる。 ディレクトリのどの位置まで読み込んだかを 示す中間状態を クッキー(cookie) という形でクライアントに返す。
クライアントは、次の RPC の呼び出しで、 前回受けとった応答の中のクッキーを、サーバへの要求に含めて送す。
const NFS_COOKIESIZE = 4; typedef opaque nfscookie[NFS_COOKIESIZE];
2.2.17. Read From Directory
struct readdirargs {
fhandle dir;
nfscookie cookie;
unsigned count;
};
struct entry {
unsigned fileid;
filename name;
nfscookie cookie;
entry *nextentry;
};
union readdirres switch (stat status) {
case NFS_OK:
struct {
entry *entries;
bool eof;
} readdirok;
default:
void;
};
readdirres
NFSPROC_READDIR (readdirargs) = 16;
Returns a variable number of directory entries, with a total size of
up to "count" bytes, from the directory given by "dir". If the
returned value of "status" is NFS_OK, then it is followed by a
variable number of "entry"s. Each "entry" contains a "fileid" which
consists of a unique number to identify the file within a filesystem,
the "name" of the file, and a "cookie" which is an opaque pointer to
the next entry in the directory. The cookie is used in the next
READDIR call to get more entries starting at a given point in the
directory. The special cookie zero (all bits zero) can be used to
get the entries starting at the beginning of the directory. The
"fileid" field should be the same number as the "fileid" in the the
attributes of the file. (See section "2.3.5. fattr" under "Basic
Data Types".) The "eof" flag has a value of TRUE if there are no
more entries in the directory.
nfsproc_readdir() で、1回目と2回目の RPC の間にディレクトリの内容が 更新された場合、どのような結果になるのか不明。
NFS非同期入出力デーモン
(
nfsiod (local NFS asynchronous I/O Daemon)
または
biod (asynchronous Block I/O Daemon)
)
は、NFSのクライアントホスト上で動き、NFSの非同期的な入出力を行う。
lockd
lockd は、受け取った要求をサーバ上の lockd に転送する。
サーバ・ホスト上の lockd は、クライアントの lockd から受け取っ
た要求をシステム・コールでカーネルに伝える。
statd
lockd は、クライアント・ホスト上の statd に問い合わせて、
クライアント・ホストがクラッシュしていないか調べる。
クライアント・ホストがクラッシュしたら、
そのクライアントから受け取っていたロック要求を解除する。
lockd には、当初からかなりバグが多かった。
初期の statd には、バッファ・オーバーフローのバグがあった。
commit() という手続きが追加。
それまでに行われた書き込みをディスクに行うように指示できる。
昔の名前は、 SMB プロトコル。 Samba は、 CIFS/SMB を、Unix 系のオペレーティング・システムで実現したプログラム。
Samba の利用法
NIS(Network Information Service)
は、/etc/hosts や /etc/passwd などを管理
するための分散型名前サービス。
名前サービスとは、名前(ホスト名, ログイン名)から、何か別の値(アドレス, パスワードやホームディレクトリなど) へ変換する。 インターネットで使われている名前サービスは、DNS 。
NIS は、1つの閉じた組織で使われることを想定して設計されている。
NISは、かつて
YP(Yellow Pages)
と呼ばれてた。YPという商標が使われていたために、途中で名前が
変った。
しかし、コマンドの名前は、以前のまま
ypXXXX になっている。
NISの主目的は、パスワード・ファイルの共有。
その他の共有できるファイル
passwd ファイルや hosts ファイルなど、
(NIS管理下の)すべてのホストで共有するファイルをNISの
マップ(map)
という。
NISでは、アクセスの高速化のために、
dbm
(または
ndbm
)
ライブラリを使って索引をつける。
例: /etc/passwd から作られるマップ
passwd.byname
csh の「~」で
使われる。
getpwnam ライブラリに対応。
passwd.byuid
ls -l で使われる。
getpwuid ライブラリに対応。
| ファイル | マップ |
| bootparams | bootparams |
| ethers | ethers.{byaddr,byname} |
| group | group.{bygid,byname} |
| hosts | hosts.{byaddr,byname} |
| aliases | mail.{aliases,byaddr} |
| netgroup | netgroup |
| netmasks | netmasks.byaddr |
| networks | networks.{byaddr,byname} |
| passwd | passwd.{byname,byuid} |
| protocols | protocols.{byname,bynumber} |
| publickey | publickey.byname |
| rpc | rpc.bynumber |
| services | services.byname |
| passwd,hosts,group | netid.byname |
| なし | ypservers |
NISのマップの集合を共有するホストの集合を、
NISの
ドメイン(domain)
という。
インターネットの DNS でいうドメインとは、別の概念。
domainmame
コマンドを使って調べたり、設定できる。
ypserv)RPC のサーバ。索引付けされたマップを管理する。
NISのサーバプロセスが走るホストの分類
ypclnt)
NISクライアントライブラリ(ypclnt)は, NISサーバに
RPCを行い、NISのマップを参照する。
例
getservbyname (get service entry by service name) ライブラリ関数。
NISの services マップを参照。
getpwent (get password file entry)
ライブラリ関数。
passwd.byname マップを参照。
ypbind)
バインドプロセス(ypbind)は、NISクライアントライブラリを
利用するホスト上で動作し、どのNISサーバを使うのかを決定するためのプロ
セス。
サーバを探す時には、
放送(broadcast)
を使って、NISのサーバプロセスが走っているかを調べ、一番先
に応答したサーバプロセスのホストを
/var/yp/ドメイン名.N
というファイルに記録する。
NISのサーバプロセスがクラッシュしたり、負荷が高くなった時には、 バインドプロセスは、再び放送を使って別のNISサーバを探す。
マスタ・サーバのホストでマップが更新されたときに、 スレーブ・サーバにマップをコピーするためのコマンド。
例:すべてのスレーブサーバに passwd.byname マップをコピーする。
# yppush passwd.byname
マスタサーバ上の /etc/ の下のファイルの日付と、対応する
マップの最終更新時刻を調べてマップを作り直す。 yppush コ
マンドを使ってスレーブサーバに転送する。
makedbm
コマンドは, /etc/ の下のファイルから, 索引つきのファイ
ルを作るコマンド。
ypxfr コマンドは、NISのスレーブサーバで、マスタサーバか
らNISのマップをコピーする時に使う。
起動方法
yppasswdd
(YP passwd daemon) は,
yp)passwd コマンド
と通信を行い、マスタサーバ上の /etc/passwd を変更する。
ypwhich
コマンドは, 現在利用しているNISサーバのホスト名を表示する。
ypset
コマンドは、ypbind に働きかけ、
利用するNISのサーバを強制的に変更する。
パスワードファイルのすり替えに使えるので、 一般ユーザからの要求は受け付けない。
NISでは, ypbind で
放送(broadcast)
を使ってサーバを探すので、放送が届く範囲に, NISのサーバを置く必要がある。
typedef string domainname<YPMAXDOMAIN>;
typedef string mapname<YPMAXMAP>;
typedef string peername<YPMAXPEER>;
typedef opaque keydat<YPMAXRECORD>;
typedef opaque valdat<YPMAXRECORD>;
enum ypstat {
YP_TRUE = 1,
YP_NOMORE = 2,
YP_FALSE = 0,
YP_NOMAP = -1,
YP_NODOM = -2,
YP_NOKEY = -3,
YP_BADOP = -4,
YP_BADDB = -5,
YP_YPERR = -6,
YP_BADARGS = -7,
YP_VERS = -8
};
struct ypreq_key {
domainname domain;
mapname map;
keydat key;
};
struct ypresp_val {
ypstat stat;
valdat val;
};
/*
* YP access protocol
*/
program YPPROG {
version YPVERS {
void
YPPROC_NULL(void) = 0;
bool
YPPROC_DOMAIN(domainname) = 1;
bool
YPPROC_DOMAIN_NONACK(domainname) = 2;
ypresp_val
YPPROC_MATCH(ypreq_key) = 3;
ypresp_key_val
YPPROC_FIRST(ypreq_key) = 4;
ypresp_key_val
YPPROC_NEXT(ypreq_key) = 5;
ypresp_xfr
YPPROC_XFR(ypreq_xfr) = 6;
void
YPPROC_CLEAR(void) = 7;
ypresp_all
YPPROC_ALL(ypreq_nokey) = 8;
ypresp_master
YPPROC_MASTER(ypreq_nokey) = 9;
ypresp_order
YPPROC_ORDER(ypreq_nokey) = 10;
ypresp_maplist
YPPROC_MAPLIST(domainname) = 11;
} = 2;
} = 100004;