定义 RX RPC 层在继续之前,您需要先定义 RX RPC 层。要实现这种功能,请为 rxgen 创建一个 .xg 文件,用来描述代理和与 afsfuse_client.c 和 afsfuse_server.c 进行链接的桩代码。清单 2 显示了如何创建一个具有如下内容的 afsfuse.xg 文件:
清单 2. 创建 afsfuse.xg 文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
| #define MYMAXPATH 512
%#include <rx/rx.h>
%#include </rx_null.h >
%#define SAMPLE_SERVER_PORT 5000
%#define SAMPLE_SERVICE_PORT 0
/* i.e. user server's port */
%#define SAMPLE_SERVICE_ID 4 /* Maximum number of requests that will be handled by this
service simultaneously */
/* This number will also be guaranteed to execute in parallel if no services' requests
are being processed */
%#define SAMPLE_MAX 2 /* Minimum number of requests that are guaranteed to be handled
immediately */
%#define SAMPLE_MIN 1 /* Index of the "null" security class in the sample service. This
must be 0 (there are N classes, numbered from 0. In this case,
N is 1) */
%#define SAMPLE_NULL 0 /********************** fuse4_file_info taken from fuse.h the
rxgen does not understands fuse.h mystat taken from man 2
mystat these are required again rxgen does not understand the
struct paras and will bump.. **********************/
struct my_file_info { /** Open flags. Available in open() and release() */
int flags; /** File handle. May be filled in by filesystem in
open(). Available in all other file operations */
unsigned int fh; /** In case of a write operation indicates if
this was caused by a writepage */
int writepage;
};
struct mystatfs {
afs_uint32 f_type; /* type of filesystem (see below) */
afs_uint32 f_bsize; /* optimal transfer block size */
afs_uint32 f_blocks; /* total data blocks in file system */
afs_uint32 f_bfree; /* free blocks in fs */
afs_uint32 f_bavail; /* free blocks avail to non-superuser */
afs_uint32 f_files; /* total file nodes in file system */
afs_uint32 f_ffree; /* free file nodes in fs */
afs_uint32 f_fsid1; /* file system id */
afs_uint32 f_fsid2; /* file system id */
afs_uint32 f_namelen; /* maximum length of filenames */
afs_uint32 f_spare[6]; /* spare for later */
};
struct mystat {
afs_uint32 st_dev; /* device */
afs_uint32 st_ino; /* inode */
afs_uint32 st_mode; /* protection */
afs_uint32 st_nlink; /* number of hard links */
afs_uint32 st_uid; /* user ID of owner */
afs_uint32 st_gid;/* group ID of owner */
afs_uint32 st_rdev; /* device type (if inode device) */
afs_uint32 st_size; /* total size, in bytes */
afs_uint32 st_blksize; /* blocksize for filesystem I/O */
afs_uint32 st_blocks; /* number of blocks allocated */
afs_uint32 st_atim; /* time of last access */
afs_uint32 st_mtim; /* time of last modification */
afs_uint32 st_ctim; /* time of last change */
};
struct my_dirhandle{
afs_uint32 type;
afs_uint32 inode;
char name[MYMAXPATH];
};
typedef my_dirhandle bulkmydirhandles<>;
/*********************phase 1 functions *********************************************/
rxc_getattr(IN string mypath<MYMAXPATH>, IN int dummy) split = 1;
rxc_getdirWrapper(IN string path<MYMAXPATH>, OUT bulkmydirhandles *handles) = 2;
rxc_read(IN string path<MYMAXPATH>;, IN afs_uint32 size, IN afs_uint32 offset,
IN struct my_file_info *fi) split = 3;
rxc_open(IN string path<MYMAXPATH>, IN int flags, OUT u_int *hd) = 4;
rxc_write(IN string path<MYMAXPATH>,IN afs_uint32 size, IN afs_uint32 offset,
IN struct my_file_info *fi) split = 5;
rxc_chmod(IN string path<MYMAXPATH>, IN afs_uint32 mode) = 6;
rxc_chown(IN string path<MYMAXPATH>, IN afs_uint32 uid, IN afs_uint32 gid) = 7;
rxc_utime(IN string path<MYMAXPATH>, IN afs_uint32 at,IN afs_uint32 mt) = 8;
rxc_mknod(IN string path<MYMAXPATH>, afs_uint32 mode, afs_uint32 rdev) = 9 ;
rxc_mkdir(IN string path<MYMAXPATH>, IN afs_uint32 mode) = 10;
rxc_unlink(IN string path<MYMAXPATH>) = 11 ;
rxc_rmdir(IN string path<MYMAXPATH>) = 12;
rxc_rename(IN string from<MYMAXPATH>, IN string to<MYMAXPATH>) = 13;
rxc_truncate(IN string path<MYMAXPATH>, IN afs_uint32 size) = 14;
rxc_release(IN string path<MYMAXPATH>, IN struct my_file_info *fi) = 15;
rxc_readlink(IN string path<MYMAXPATH>, IN afs_uint32 size,OUT string
data<MYMAXPATH>) = 16;
rxc_symlink(IN string from<MYMAXPATH>, IN string to<MYMAXPATH>) = 17;
rxc_link(IN string from<MYMAXPATH>, IN string to<MYMAXPATH>) = 18;
rxc_statfs(IN string path<MYMAXPATH>, OUT struct mystatfs *stbuf) = 19;
rxc_fsync(IN string path <MYMAXPAT>, IN int isdatasync, IN struct my_file_info
*fi) = 20 ;
rxc_flush(IN string path <MYMAXPATH>, IN struct my_file_info *fi) = 21 ;
|
在定义 RX RPC 层时,注意以下几点:
- 在 statfs、stat 和 fuse_file_info 基础上定义了 mystatfs、mystat 和 my_file_info 的封装程序。它们都会使用所生成的 XDR 代码进行转换。(XDR(External Data Representation,外部数据表示)允许采用一种与体系结构无关的方式进行封装,这样就可以在异构计算机系统之间传输数据了。)
- 您几乎要为 fuse_operations 结构的每个成员都定义一个函数,它们几乎具有相同的参数,因为 afsfuse_client 的工作就是负责接管 FUSE 文件系统中的调用,并将这些调用传递给 afsfuse_server。
- 您已经硬编码了一些值,例如 MYMAXPATH,这应该从系统中获得 —— 硬编码是为了简单性起见而这样做的。
创建客户机和存根文件接下来使用 rxgen 编译 afsfuse.xg 文件,从而创建客户机和存根文件。从包含 afsfuse_server 和 afsfuse_client 的源代码的目录中,运行命令 openafs-1.2.13/i386_linux24/dest/bin/rxgen afsfuse.xg。这会创建以下文件:
- afsfuse.cs.c 是与 afsfuse_client.c 进行链接的客户机存根代码。
- afsfuse.h 是包含您的 FUSE RX 代码的各种定义的头文件。
- afsfuse.ss.c 是与 afsfuse_server 代码进行链接的服务器存根代码(代理代码)。
- afsfuse.xdr.c 包含了用来处理在 afsfuse.xg 中定义的 3 个结构所使用的代码。
现在为 afsfuse_client.c 和 afsfuse_server.c 添加一些执行实际工作的代码。大部分调用都如下所示:
- Our_call_in_afs_fuse_client()。分析参数并准备执行 RPC。对 RX [RPC] 调用 afsfuse_server。组合参数。将这些值拷贝到传递给这个函数的行参数中。
- Our_call_in_afs_fuse_server()。组合参数。调用本地文件系统或 AFS 特有的函数。分析参数准备执行 RPC。生成 RX RPC 调用。
afsfuse_client.c 调用如下所示:
1
2
3
4
5
6
7
8
9
| int afsfuse_readlink(const char *path, char *buf, size_t size){
rx_connection *local& int ret& char *buffer = malloc (512)&
memset(buffer,0,512)& memset(buf,0,size)& local = getconnection()&
ret = rxc_rxc_readlink(local,path,512,&buffer) // rpc call
relconnection(local)&
strncpy(buf,buffer,512-1)&
//<- demarshall the parametrs
return ret&
}
|
afsfuse_server.c 调用如下所示:
清单 3. afsfuse_server.c 调用1
2
3
4
5
6
7
| int rxc_rxc_readlink( struct rx_call *call, char * path, afs_uint32 size, char**data)
{ int ret& char lbuff[512] ={0}&
translatePath(path,lbuff)& //<- make filesystem call
*data = malloc(512)&
res = readlink(lbuff, *data, 512-1)&
if(res == -1) return -errno& (*data)[res] = '\0'& return 0&
}
|
简单地,您可以在其他函数中添加代码来对文件系统进行增强。
您需要创建一个 makefile 来编译代码。记住在编译 afsfuse_client 的代码时包括以下选项:-D_FILE_OFFSET_BITS=64 和 -DFUSE_USE_VERSION=22。
清单 4. 生成编译客户机代码使用的 makefile1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| SRCDIR=./ LIBRX=${SRCDIR}lib/librx.a
LIBS=${LIBRX} ${SRCDIR}lib/liblwp.a
#CC = g++
CFLAGS=-g -I. -I${SRCDIR}include -I${SRCDIR}include/fuse/ -DDEBUG ${XCFLAGS}
-D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=22
afsfuse_client: afsfuse_client.o afsfuse.xdr.o ${LIBS} bulk_io.o afsfuse.cs.o
${CC} ${CFLAGS} -o afsfuse_client afsfuse_client.o ${SRCDIR}lib/fuse/fuse.o
${SRCDIR}lib/fuse/mount.o ${SRCDIR}lib/fuse/helper.o
${SRCDIR}lib/fuse/fuse_mt.o bulk_io.o afsfuse.cs.o afsfuse.xdr.o ${LIBS}
afsfuse_server: afsfuse_server.o afsfuse.xdr.o afsfuse.ss.o bulk_io.o ${LIBS}
${CC} ${CFLAGS} -o afsfuse_server afsfuse_server.o bulk_io.o afsfuse.ss.o
afsfuse.xdr.o ${LIBS}
#afsfuse_client.o: afsfuse.h
#afsfuse_server.o: afsfuse.h
bulk_io.o: ${CC} -c -g -I${SRCDIR}include bulk_io.c afsfuse.cs.c afsfuse.ss.c
afsfuse.er.c afsfuse.h afsfuse.xdr.c: afsfuse.xg rxgen afsfuse.xg
afsfuse.xdr.o: afsfuse.xdr.c ${CC} -c -g -I{SRCDIR}include afsfuse.xdr.c
all: afsfuse_server afsfuse_client
clean: rm *.o rm afsfuse_client rm afsfuse_server
|
记住,您仍然需要使用 librx.a 和 liblwp.a 链接到 RX 和 RX 使用的 LWP 代码上。fuse/fuse.o、fuse/helper.o 和 fuse/mount.o 都是代码需要链接的 FUSE 库。 |