Linux下RPC调用编程
- 格式:doc
- 大小:42.50 KB
- 文档页数:9
Linux下RPC调用编程作者:来源:/linux_coder 发表时间:2007-05-01 浏览次数:26823 字号:大中小中国源码网内相关主题链接∙Linux 2.6内核中新的锁机制--RC U∙XML-RPC in Py thon简介∙Linux起源与GNU简介∙linux设置环境变量的方法∙c++文件调用c头文件注意事项∙linux下使用minicom的几个命令∙linux内核编译问题∙递归函数的调用过程linux rpc在内核中实现,源代码位置是net/sunrpc/sunrpc不仅实现了rpc的调度,同时将rpc请求构造解析发送接受的通用部分进行了提取。
要定义自己的rpc调用仅需要实现那些非通用的部分,下面简要介绍怎么实现一个自己的rpc客户端(2.4内核)主要数据结构介绍1。
rpc请求/**This is the RPC buffer*/struct rpc_iov{struct iov ec io_v ec[MA X_IOVEC]; //使用10个iov ec 可以操作分散的bufferunsigned int io_nr;unsigned int io_len;};/**This describes a complete RPC request*/struct rpc_rqst {/**This is the user-v isible part*/struct rpc_xprt * rq_xprt; /* RPC client */struct rpc_timeout rq_timeout; /* timeout parms */struct rpc_iov rq_snd_buf; /* send buffer 发送缓冲区*/ struct rpc_iov rq_rcv_buf; /* rec v buffer 接受缓冲区*//**This is the priv ate part*/struct rpc_ta sk * rq_task; /* RPC task data */__u32 rq_xid; /* request XID */struct rpc_rqst * rq_next; /* free list */v olatile unsigned char rq_receiv ed : 1;/* receiv e completed *//**F or authentication (e.g. auth_des)*/u32 rq_creddata[2];/**Partial send handling*/u32 rq_by tes_sent; /* By tes w e hav e sent */#ifdef RPC_PROFILEunsigned long rq_xtime; /* w hen transmitted */ #endif};#define rq_sv ec rq_snd_buf.io_v ec#define rq_snr rq_snd_buf.io_nr#define rq_slen rq_snd_buf.io_len#define rq_rv ec rq_rcv_buf.io_v ec#define rq_rnr rq_rcv_buf.io_nr#define rq_rlen rq_rcv_buf.io_len流程介绍1。
注册自己的rpc调用#ifndef MA X#define MA X(a, b) (((a) > (b))? (a) : (b))#endif#define PROC(proc, argty pe, resty pe, timer) \{ "xxx_clnt" #proc, \(kxdrpro c_t) xxx_clnt_encode_##argty pe, \(kxdrpro c_t) xxx_clnt_deco de_##resty pe, \MA X(XXX_##argty pe##_sz,XXX_##resty pe##_sz) , \timer \}// 这里注册了3个rpc调用,分别是:read、w rite、getsizestatic struct rpc_procinfo xxx_clnt_pro cedures[4] = {PROC(null, v oid, v oid, 0),PROC(read, readargs, readres, 0),PROC(w rite, w riteargs, w riteres, 0),PROC(getsize, getsizeargs, getsizeres, 0),}/*上面结构实际效果是下面这样其中注册了每个rpc请求和返回的编码解码函数,在步骤4中描述static struct rpc_procinfo xxx_clnt_pro cedures[4] = {{"xxx_clnt_null", (kxdrpro c_t)xxx_clnt_encode_v oid, (kxdrpro c_t)xxx_clnt_decode_v oid, MA X(XXX_v oid_sz, XXX_v oid_sz), 0}, {"xxx_clnt_read", (kxdrproc_t)xxx_clnt_enco de_readargs, (kxdrproc_t)xxx_clnt_deco de_readres, MA X(XXX_reada rgs_sz, XXX_re adres_sz), 0},{"xxx_clnt_w rite", (kxdrproc_t)xxx_clnt_encode_w riteargs, (kxdrpro c_t)xxx_clnt_de code_w riteres, MA X(XXX_w riteargs_sz, XXX_w riteres_sz), 0},{"xxx_clnt_getsize", (kxdrpro c_t)xxx_clnt_encode_getsizeargs, (kxdrproc_t)xxx_clnt_decode_getsizeres, MA X(XXX_getsizea rgs_s z, XXX_getsizeres_sz), 0},};*/static struct rpc_v ersion xxx_clnt_v ersion1 = {1,sizeof(xxx_clnt_procedures)/sizeof(xxx_clnt_pro cedures[0]),xxx_clnt_procedures};static struct rpc_stat xxx_clnt_rpcstat;static struct rpc_v ersion* xxx_clnt_v ersion[] = {NU LL,&xxx_clnt_v ersion1,};struct rpc_pro gram xxx_clnt_program = {"xxx",XXX_PRO GRAM,sizeof(xxx_clnt_v ersion)/sizeof(xxx_clnt_v ersion[0]),xxx_clnt_v ersion,&xxx_clnt_rpcstat,};2。
在运行前先创建rpc调度线程if (rpcio d_up() != 0) {printk("xxx:unable to run asy nc scheduler!\n");return -1;}3。
实现rpc调用函数以read为例struct xxx_reada rgs readargs; //用户自定义请求参数结构struct xxx_readres readres; //用户自定义请求返回结构struct rpc_message read_msg = {1,&readargs, //以指针形式注册到rpc消息结构中&readres,NU LL,};// 同步的情况int xxx_read(???){int retv al = 0;// 设置发送的属性readargs.??? = ??;readargs.??? = ??;// 设置返回参数的属性readres.??? = ??;retv al = rpc_call_sy nc(xxx_clnt, &read_msg, 0);if (retv al < 0){// 出错情况} else {// 获取返回值}return retv al;}4。
rpc调用参数和返回值的解析函数步骤3中有用户自定义的参数返回值struct xxx_reada rgs readargs; //用户自定义请求参数结构struct xxx_readres readres; //用户自定义请求返回结构在进行socket包发送接受时需要进行它们的编码和解析主要是为了便利用户定义参数的灵活性,比如数据可以通过iov ec分散的保存下面是nfs的编码函数// 用户自定义的请求结构指针args被传入函数static intnfs3_xdr_w riteargs(struct rpc_rqst *req, u32 *p, struct nfs_w riteargs *args) {unsigned int nr;u32 count = args->count;// 部分属性参数的打包p = xdr_encode_fhandle(p, args->fh);p = xdr_encode_hy per(p, args->offset);*p++ = htonl(count);*p++ = htonl(args->stable);*p++ = htonl(count);req->rq_slen = xdr_a djust_iov ec(req->rq_sv ec, p);/*Get the number of buffers in the send iov ec */nr = args->nriov;if (nr+2 > MA X_IOVEC){// rpc请求只能最大支持10个iov ecprintk(KERN_ERR "NFS: Bad number of iov's in xdr_w riteargs\n");return -EINVA L;}/*Copy the iov ec 通过拷贝iov ec到将要发送的数据导入到了rpc里面*/ memcpy(req->rq_sv ec + 1, args->iov, nr * sizeof(struct iov ec));req->rq_slen += count;req->rq_snr += nr;return 0;}。