情報学類 分散システム 2007年01月30日 筑波大学システム情報工学研究科 コンピュータサイエンス専攻, 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2006/2007-01-30
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~yas/
http://www.cs.tsukuba.ac.jp/~yas/
rpcgen
というコマンド。
rpcgen
コマンドを使うには、次のようなファイルを作成する。
図? rpcgenによるRPCプログラム開発で利用するファイル
name.x
name_client.c
name_server.c
% rpcgen name.x次の4つのファイルが生成される。![]()
name.h
name_clnt.c
name_xdr.c
name.x
で定義したデータ構造について、
XDR
のための手続き(整列化と非整列化を行なう手続き) 。
クライアント側とサーバ側の両方で使われる。
name_svc.c
/etc/rpc
にある。
SunRPCでは, 最終的にはTCP/IPまたはUDP/IPでデータが送られる。プログラム 番号などTCP/IPまたはUDP/IPのポート番号を対応させる必要がある。
各ホストには
portmap
というサーバがいて、3つ組
portmap の情報は、
rpcinfo
コマンドで表示できる。
% rpcinfo -p他のホストの情報も調べられる。program vers proto port 100000 2 tcp 111 portmapper 100000 2 udp 111 portmapper 100007 2 tcp 1024 ypbind 100007 2 udp 1027 ypbind 100007 1 tcp 1024 ypbind 100007 1 udp 1027 ypbind 100005 1 udp 831 mountd 100005 2 udp 831 mountd 100005 1 tcp 834 mountd 100005 2 tcp 834 mountd 100003 2 udp 2049 nfs 100001 2 udp 4193 rstatd 100001 3 udp 4193 rstatd 100001 4 udp 4193 rstatd %
![]()
% rpcinfo -p hostnameサーバは、起動時に、portmap に登録する。![]()
pmap_set(prognum, versnum, protocol, port) u_long prognum, versnum, protocol; u_short port;クライアントは、呼び出す前に、ポート番号を調べる。
u_short pmap_getport(addr, prognum, versnum, protocol)
スタブが自動的に呼び出すので、普段は気にすることはない。
portmap 自身も RPC で動いている。portmap の自身のポート番号は、111 と 決まっている。
1: struct delist { 2: string del_name<> ; 3: struct delist *del_next ; 4: }; 5: 6: union dirlist_res 7: switch(int dlr_errno) 8: { 9: case 0: 10: delist *dlr_head; 11: default: 12: void; 13: }; 14: 15: program DIRLIST_PROG { 16: version DIRLIST_VERSION { 17: dirlist_res DIRLIST(string) = 11 ; 18: } = 1; 19: } = 0x20001003 ;17行目が手続きの定義。
DIRLIST
が手続きの名前(手続き番号を示す定数の定義)。
この手続きの引数は、string
型、結果は、dirlist_res
型。SunRPC では、基本的には引数も結果も1つずつ。複数必要な時には、構造体を
定義する。
手続き DIRLIST
の定義を program
番号と
version
番号の括弧が取り囲んでいる。
dirlist_res は、共用体(可変長の構造体、Pascal 可変長レコード)。
struct delist は、自分自身へのポインタ(del_next)を含むリスト構造。
一般的に RPC では、ポインタを含むデータ構造を送ることはできない。 SunRPC では、ポインタの先の1要素を再帰的に送る機能がある。 これにより、木構造や線形リストを送ることができる。
string del_name<> は、文字列型。可変長(<>)で最 大文字数には定められていない(<>の中が空)。
ヘッダファイルの主要部分は、以下の通りである。
struct delist { char *del_name; struct delist *del_next; }; typedef struct delist delist; struct dirlist_res { int dlr_errno; union { delist *dlr_head; } dirlist_res_u; }; typedef struct dirlist_res dirlist_res; #define DIRLIST_PROG ((u_long)0x20001003) #define DIRLIST_VERSION ((u_long)1) #define DIRLIST ((u_long)11) extern dirlist_res * dirlist_1(char **, CLIENT *); extern dirlist_res * dirlist_1_svc(char **, struct svc_req *);
: /* 2: dirlist_server.c -- ディレクトリの内容を表示するRPCのプログラム(サーバ側) 3: Created on: 2006/01/18 20:33:31 4: */ 5: 6: #include <sys/types.h> /* opendir(2) */ 7: #include <dirent.h> /* opendir(2) */ 8: #include <errno.h> /* errno */ 9: #include <stdlib.h> /* malloc() */ 10: #include <string.h> /* strlen() */ 11: #include <stdio.h> /* snprintf() */ 12: 13: #include "dirlist.h" 14: static struct delist *make_delist( DIR *dirp ); 15: 16: dirlist_res * 17: dirlist_1_svc(char **argp, struct svc_req *rqstp) 18: { 19: static dirlist_res result; 20: DIR *dirp ; 21: char *dirname ; 22: 23: xdr_free((xdrproc_t)xdr_dirlist_res, (char *)&result); 24: 25: dirname = *argp ; 26: dirp = opendir( dirname ); 27: if( dirp == 0 ) 28: { 29: result.dlr_errno = errno ; 30: return( &result ); 31: } 32: result.dlr_errno = 0; 33: result.dirlist_res_u.dlr_head = make_delist( dirp ); 34: closedir( dirp ); 35: return( &result ); 36: } 37:サーバ側では、手続き dirlist_1_svc() を記述する。 引数と結果は、
rpcgen
のソースで定義した構造体へのポインタ。
結果を返す時の構造体へのポインタを返す方法が問題。自動変数(auto 変数) にすると、呼出し側に戻った瞬間に無効になる。よく使われるのは、静的変数 (static 変数)に結果を代入して、返すことだが、マルチスレッドプログラミ ングでは大いに問題になる。
opendir(), readdir(), closedir() は、ディレクトリの内容を得るためのラ イブラリ関数。次のようなコードで、"/" の内容が表示される(ls -f /)。
dirp = opendir( "/" ); while( (dp = readdir(dirp)) != NULL ) { printf("%s\n", dp->d_name ); } closedir( dirp );readdir() は、make_delist() の中で行われる。
38: static struct delist * 39: make_delist( DIR *dirp ) 40: { 41: struct dirent *dp ; 42: struct delist *del ; 43: int namelen; 44: if( (dp = readdir(dirp)) == NULL ) 45: { 46: return( 0 ); 47: } 48: else 49: { 50: del = malloc(sizeof(struct delist)); 51: namelen = strlen( dp->d_name ); 52: del->del_name = malloc( namelen+1 ); 53: snprintf(del->del_name,namelen+1,"%s",dp->d_name ); 54: del->del_next = make_delist( dirp ); 55: return( del ); 56: } 57: }make_delist() は、再帰呼び出しで、struct delist のリストを作る。
自動生成されるサーバのmainプログラムでは、 ポートマッパ(port mapper) へのプログラム番号とバージョン番号の登録される。
1: /* 2: dirlist_client.c -- ディレクトリの内容を表示するRPCのプログラム(クライアント側) 3: Created on: 2006/01/18 20:57:49 4: */ 5: 6: #include <stdlib.h> /* exit() */ 7: #include <stdio.h> /* printf() */ 8: 9: #include "dirlist.h" 10: 11: main( int argc, char *argv[] ) 12: { 13: if( argc != 3 ) 14: { 15: fprintf(stderr,"usage: %% %s server_host dir\n", argv[0]); 16: exit( 1 ); 17: } 18: dirlist( argv[1], argv[2] ); 19: } 20: 21: dirlist(char *host, char *dir) 22: { 23: CLIENT *clnt; 24: dirlist_res *result; 25: char *arg; 26: 27: clnt = clnt_create (host, DIRLIST_PROG, DIRLIST_VERSION, "tcp"); 28: if( clnt == NULL ) 29: { 30: clnt_pcreateerror( host ); 31: exit( 1 ); 32: } 33: 34: arg = dir; 35: result = dirlist_1( &arg, clnt ); 36: if( result == NULL ) 37: { 38: clnt_perror( clnt, "call failed"); 39: exit( 1 ); 40: } 41: print_dirlist_res( result ); 42: xdr_free( (xdrproc_t)xdr_dirlist_res, (char *)result ); 43: clnt_destroy( clnt ); 44: } 45:
main() の引数は、サーバが動作しているホスト名とディレクトリ。
clnt_create()
は、CLIENT
構造体を確保する。
引数は、サーバのホスト名、
プログラム番号、
バージョン番号、
通信に使うプロトコルである。
33行目で呼び出している dirlist_1()
が、rpcgen
によ
り生成されたスタブ。引数は、インタフェースで定義された構造体
dirlistarg
へのポインタと、CLIENT
構造体へ
のポインタ。結果は、インタフェースで定義された構造体
dirlistres
へのポインタである。この関数は、rpcgen
が生成する *_clnt.c
というファイルに含まれてる。
スタブ dirlist_1()
は、成功すると内部で malloc()
を呼
び出しメモリを確保して、そこにサーバから受け取った応答メッセージを
非整列化(unmarshalling)
して保存する。このメモリは、利用し終わると xdr_free()
で
解放する。
free( result );だと、トップレベルの構造体のメモリしか解放されない。内部に含まれている 構造体へのポインタや文字列のメモリを解放するためには、
xdr_free()
を呼び出す。
46: print_dirlist_res( dirlist_res *result ) 47: { 48: printf("errno: %d (%s)\n", 49: result->dlr_errno, strerror(result->dlr_errno)); 50: switch( result->dlr_errno ) 51: { 52: case 0: 53: print_delist( result->dirlist_res_u.dlr_head ); 54: break; 55: default: 56: break; 57: } 58: } 59: 60: print_delist( struct delist *del ) 61: { 62: if( del == NULL ) 63: { 64: } 65: else 66: { 67: printf("%s\n",del->del_name ); 68: print_delist( del->del_next ); 69: } 70: }print_dirlist_res() は、struct dirlist_res を表示する。 print_delist() は、struct delist を表示する。 構造体が再帰している所で、関数も再帰している。
% wget http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2006/2007-01-30/ex/dirlist.xSolaris, Linux では、-lnsl が必要。Solaris, MacOSX では、-DDEBUG をつ けてコンパイルとfork() しないでフォアグランドで動くサーバができる。% wget http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2006/2007-01-30/ex/dirlist_server.c
% wget http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2006/2007-01-30/ex/dirlist_client.c
% wget http://www.coins.tsukuba.ac.jp/~yas/coins/dsys-2006/2007-01-30/ex/Makefile
% emacs Makefile
% make
rpcgen dirlist.x gcc -g -DDEBUG -c -o dirlist_clnt.o dirlist_clnt.c gcc -g -DDEBUG -c -o dirlist_client.o dirlist_client.c gcc -g -DDEBUG -c -o dirlist_xdr.o dirlist_xdr.c gcc -g -DDEBUG -o dirlist_client dirlist_clnt.o dirlist_client.o dirlist_xdr.o -lnsl gcc -g -DDEBUG -c -o dirlist_svc.o dirlist_svc.c gcc -g -DDEBUG -c -o dirlist_server.o dirlist_server.c gcc -g -DDEBUG -o dirlist_server dirlist_svc.o dirlist_server.o dirlist_xdr.o -lnsl %
![]()
% ./dirlist_serverサーバ側は自動的には止まらないので、止めたい時には、![]()
^C
を押す。
サーバを動かしているホストの別の端末で rpcinfo -p を実行すると、プログ ラム番号536875011 (0x20001003) のプログラムが表示される。
% rpcinfo -pprogram vers proto port 100000 2 tcp 111 portmapper 100000 2 udp 111 portmapper 100024 1 udp 1013 status 100024 1 tcp 974 status 100021 0 udp 1000 nlockmgr 100021 1 udp 1000 nlockmgr 100021 3 udp 1000 nlockmgr 100021 4 udp 1000 nlockmgr 100021 0 tcp 973 nlockmgr 100021 1 tcp 973 nlockmgr 100021 3 tcp 973 nlockmgr 100021 4 tcp 973 nlockmgr 536875011 1 udp 53972 536875011 1 tcp 60723 %
![]()
MacOSX 10.4 では、portmapp が動作していないことがある。rpcinfo -p で何 も表示されない時には、root で 次のようにして実行する。
launchctl start com.apple.portmap
% ./dirlist_client localhost /usrerrno: 0 (Unknown error: 0) . .. .DS_Store bin epkg include info lib libexec local local3 sbin share standalone X11R6 %
![]()
整数: char, short, int (32ビット), long, long long (hyper, 64ビット)
各 unsigned。
浮動小数点: float, double, (quadruple 4倍精度)
ほぼC言語と同等に書ける。自動的に typedef される。 ほぼC言語と同等に書れる。自動的に typedef される。RPCのインタフェースの定義では、定数を記述することができる。
const LSIZE = 80 ;これは、
rpcgen
により、C言語のプリプロセッサのマクロ
#define
に置き換えられる。
RPCのインタフェースの定義では、配列を定義することができる。配列には、
固定長と可変長の2種類あり、固定長は、C言語と同じ。可変長は、次のよう
に[]
の代わりに<>
とする。
int varray<>;
<>
の中には、最大長を書くこともできる。これは、
rpcgen
により、次のような構造体に置き換えられる。
struct { u_int varray_len; int *varray_val; } varray; typedef struct varray varray ;C言語でプログラムを作成する時には、この
varray_len
に要素数を、
varray_val
に、配列の先頭のポインタをセットする。
int a1[10] ; varray v1 ; v1.varray_len = 10 ; v1.varray_val = &a1[0] ;文字列を送るには、特殊な
string
型を使う。
string s<> ;これは、C言語では、
char *
になるが、文字列のつもりで次のよう
に書いても、文字列は送られない。
char *s ;これも、
rpcgen
により、やはり char *
にコンパイルされる
が、この場合、ポインタの先の1文字しか送られない。C言語の文字列を送り
たい時には、必ず string
を使うこと。
SunRPC ではポインタ型も送ること ができるが、ポインタの先の1要素しか送られない。 複数要素を送りいた時には、配列を使う。
C言語の main の引数と同様の構造を送りたい時には、次のようにする。
typedef string argstr_t<>; typedef argstr_t argvt<>;大量のデータをそのまま送るには、
opaque
型
(
不定形型
)
を使う。これには固定長と可変長がある。
opaque fileblock[512] ; opaque filedata<> ;
opaque
の代わりにchar
の配列にすると、文字と見なして1
文字1文字変換が行なわれることになり、非常に遅くなる。場合によっては文
字コードの変換が行なわれる。opaque
では、そのような変換は一切
行なわれず、そのままの形で送られる。
RPCのインタフェースの定義では、共用体(可変長の構造体)が書ける。
union int_result_t switch( int status ) { case OK: int data ; default: void; };これは、次のようにコンパイルされる。
struct int_result_t { int status; union { int data; } int_result_t_u; };
status
という値がOK
の時だけdata
が有効になる。
すなわち、その時だけ実際にネットワークにたいしてdata
の部分が
送られる。
RPCのインタフェースの定義では、
bool_t
という型が使える。値は、
TRUE
か FALSE
。
Sunの技術で、構造体をファイルに保存することができる。
構造体を整列化し、他のプロセスに通信メッセージとして送る代わりにファイ ルに保存する。
SunRPCでは、xdrstdio_create() という関数が用意されている。 ストリーム入出力(FILE *) に対して構造体を読み書きすることができるようになる。
RPCと同様に、構造体にポインタが含まれていた場合、再帰的にファイルに保 存される。異なる機種で読み出すことができる。
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 の利用法
cl = clnt_create(server, NFS_PROGRAM, NFS_VERSION, "udp"); cl->cl_auth = authunix_create_default();NFSPROC_LOOKUP を呼び出すプログラムが次のファイルにある。 これを参考にするとよい。
~yas/public_html/coins/dsys-2006/2007-01-30/nfs/lookup.c
ヒント:stat() システムコールや lstat() システムコールでファイルの属性 を得る。RPC では、単に string を返すのではなく、属性も返す。 返す属性は、自分で .x ファイルに定義して、struct stat からコピーする。
struct stat にある属性のうち、数個を送ればよい。全てを送らなくてもよい。
注意:putenv() の引数は、strdup() すること。(同じ名前の環境変数がある と、ゴミが出てきてしまうが、この課題では問題ないとする。)
typedef string key_t<256>; struct keyvalue_t { key_t key; int value ; }; typedef key_t keyarray_t<>; program HASHTABLE_PROG { version HASHTABLE_VERSION { int PUT(keyvalue_t) = 11 ; int GETVALUE(key_t) = 12 ; keyarray_t GETKEYS(void) = 13 ; } = 1 ; } = 0x20051001 ;
まず、次のような「テキストファイル」を作成する。漢字コードとしては、 JIS、Shift-JIS、EUC を受け付ける。(PDF, RTF, ワープロの文書ファイルで は受付ない。テキストでも Unicode (UTF) は、受け付けない。ZIP や tar, gzip 等で固めたり圧縮しないように。)
---------------------------------------------------------------------- 学籍番号: 200404321 名前: 漢字の名前 課題番号:M 練習問題番号:N 題名:subject <内容> ----------------------------------------------------------------------本文の先頭に学籍番号と名前(漢字の名前がある人は、漢字で)を書きなさい。 課題番号としては、「1」 と記述しなさい。 練習問題番号とは「★練習問題」に続いて表示されている番号である。 題名には、電子メールの Subject: と同様に、内容に即したものをつける。
<内容>は、日本語(または英語)で書きなさい。文章には、述語を付ける。 体言止めは、使ってはならない。単にプログラムを含めるのではなく、「以下 に○○のプログラムを示す」と書くこと。<内容>には、プログラムだけでな く、実行結果(入力と出力)と説明をつける。
問題を難しい方に変えてた場合、または、最初から難しい問題を解いた場合に は、<内容>の部分で主張しなさい。
作成したファイルを、次のページから投稿する。
上で書いた課題番号、題名を繰り返し指定する。さらに、WWW ブラウザの機能 を使って作成したレポートのファイルを選択する。 最後に、「提出」ボタンを押す。
提出されたレポートは、次のボタンで表示できます。
もし、提出に失敗したり、提出には成功しても確認画面に現れない場合には、 新城(yas@is.tsukuba.ac.jp)かTAに、連絡しなさい。
レポートを再提出する時には、どの部分を修正したのかが簡単にわかるように 説明しなさい。
提出したレポートは、講義が終るまで保存しなさい。