结合 fuse 和 rpc 来列出远程目录

Posted

技术标签:

【中文标题】结合 fuse 和 rpc 来列出远程目录【英文标题】:combine fuse and rpc for remote directory listing 【发布时间】:2013-12-23 15:15:06 【问题描述】:

我正在开发一个带有 fuse 的自定义文件系统。我想要做的是从远程服务器读取目录的内容并将它们列出在挂载点中。我的 rpc 程序运行良好。但是当我尝试将它与 rpc 结合时,它出现了一些构建错误。我正在使用 rpcgen 创建我的 rpc 程序,但我不知道应该如何将它们一起构建。

这是我的 cfs_client.c:

/*
  FUSE: Filesystem in Userspace
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>

  This program can be distributed under the terms of the GNU GPL.
  See the file COPYING.

  gcc -Wall cfs.c `pkg-config fuse --cflags --libs` -o cfs
 */

#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "cfs.h"

static const char *cfs_str = "Hello World!\n";
static const char *cfs_path = "/cfs";

static int cfs_getattr(const char *path, struct stat *stbuf) 
    int res = 0;

    memset(stbuf, 0, sizeof (struct stat));
    if (strcmp(path, "/") == 0) 
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
     else if (strcmp(path, cfs_path) == 0) 
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = strlen(cfs_str);
     else
        res = -ENOENT;

    return res;


static int cfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
        off_t offset, struct fuse_file_info *fi) 
    (void) offset;
    (void) fi;
    char *host = "localhost";
    char *dirname = "/home/hamed/test";
    CLIENT *clnt;
    readdir_res *result_1;

    if (strcmp(path, "/") != 0)
        return -ENOENT;

#ifndef DEBUG
    clnt = clnt_create(host, CFSPROG, CFSVERS, "udp");
    if (clnt == NULL) 
        clnt_pcreateerror(host);
        exit(1);
    
#endif  /* DEBUG */
    result_1 = readdir_1(&dirname, clnt);
    if (result_1 == (readdir_res *) NULL) 
        clnt_perror(clnt, "call failed");
    
    namelist nl;
    nl = result_1->readdir_res_u.list;
    while (nl) 
        printf("dirname = %s\n", nl->name);
        filler(buf, nl->name, NULL, 0);
        nl = nl->next;
    

#ifndef DEBUG
    clnt_destroy(clnt);
#endif   /* DEBUG */

    return 0;


static int cfs_open(const char *path, struct fuse_file_info *fi) 
    if (strcmp(path, cfs_path) != 0)
        return -ENOENT;

    if ((fi->flags & 3) != O_RDONLY)
        return -EACCES;

    return 0;


static int cfs_read(const char *path, char *buf, size_t size, off_t offset,
        struct fuse_file_info *fi) 
    size_t len;
    (void) fi;
    if (strcmp(path, cfs_path) != 0)
        return -ENOENT;

    len = strlen(cfs_str);
    if (offset < len) 
        if (offset + size > len)
            size = len - offset;
        memcpy(buf, cfs_str + offset, size);
     else
        size = 0;

    return size;


static struct fuse_operations cfs_oper = 
    .getattr = cfs_getattr,
    .readdir = cfs_readdir,
    .open = cfs_open,
    .read = cfs_read,
;

int main(int argc, char *argv[]) 
    return fuse_main(argc, argv, &cfs_oper, NULL);

这是我的 cfs_server.c:

/*
 * This is sample code generated by rpcgen.
 * These are only templates and you can use them
 * as a guideline for developing your own functions.
 */

#include "cfs.h"
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <rpc/pmap_clnt.h>

readdir_res * readdir_1_svc(nametype *dirname, struct svc_req *rqstp) 
    DIR *dp;
    struct dirent *directory;
    static readdir_res result;
    int inode;
    namelist nl;
    namelist *nlp;

    dp = opendir(*dirname);
    if (dp != NULL) 
        nlp = &result.readdir_res_u.list;
        while (directory = readdir(dp)) 
            nl = *nlp = (namenode *) malloc(sizeof (namenode));
            nl->name = directory->d_name;
            nlp = &nl->next; 
        
    
        *nlp = NULL;
       result.errnum = 0;
        closedir(dp);

    return &result;

这是我使用的制作文件:

# This is a template Makefile generated by rpcgen

# Parameters

CLIENT = cfs_client
SERVER = cfs_server

SOURCES_CLNT.c = 
SOURCES_CLNT.h = 
SOURCES_SVC.c = 
SOURCES_SVC.h = 
SOURCES.x = cfs.x

TARGETS_SVC.c = cfs_svc.c cfs_server.c cfs_xdr.c 
TARGETS_CLNT.c = cfs_clnt.c cfs_client.c cfs_xdr.c 
TARGETS = cfs.h cfs_xdr.c cfs_clnt.c cfs_svc.c cfs_client.c cfs_server.c

OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags 

CFLAGS += -g -Wall -DRPC_SVC_FG $(shell pkg-config fuse --cflags --libs)
LDLIBS += -lnsl
RPCGENFLAGS = -g

# Targets 

all : $(CLIENT) $(SERVER)

$(TARGETS) : $(SOURCES.x) 
    rpcgen $(RPCGENFLAGS) $(SOURCES.x)

$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c) 

$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c) 

$(CLIENT) : $(OBJECTS_CLNT) 
    $(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS) 

$(SERVER) : $(OBJECTS_SVC) 
    $(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)

 clean:
     $(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)

编辑: 错误是:

root@debian:/programs/c/rpc/custom file system# make -f Makefile.cfs
rpcgen -g cfs.x
usage: rpcgen infile
    rpcgen [-abkCLNTM][-Dname[=value]] [-i size] [-I [-K seconds]] [-Y path] infile
    rpcgen [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] [-o outfile] [infile]
    rpcgen [-s nettype]* [-o outfile] [infile]
    rpcgen [-n netid]* [-o outfile] [infile]
options:
-a      generate all files, including samples
-b      backward compatibility mode (generates code for SunOS 4.1)
-c      generate XDR routines
-C      ANSI C mode
-Dname[=value]  define a symbol (same as #define)
-h      generate header file
-i size     size at which to start generating inline code
-I      generate code for inetd support in server (for SunOS 4.1)
-K seconds  server exits after K seconds of inactivity
-l      generate client side stubs
-L      server errors will be printed to syslog
-m      generate server side stubs
-M      generate MT-safe code
-n netid    generate server code that supports named netid
-N      supports multiple arguments and call-by-value
-o outfile  name of the output file
-s nettype  generate server code that supports named nettype
-Sc     generate sample client code that uses remote procedures
-Ss     generate sample server code that defines remote procedures
-Sm         generate makefile template 
-t      generate RPC dispatch table
-T      generate code to support RPC dispatch tables
-Y path     directory name to find C preprocessor (cpp)

For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
make: *** [cfs_clnt.c] Error 1

【问题讨论】:

"...但是当我尝试将它与 rpc 结合使用时,出现了一些构建错误";那是什么构建错误? 我通过添加构建错误来编辑我的问题。 【参考方案1】:

我已经通过使用 bash 文件解决了我的问题。这是我的脚本,给那些可能和我有同样问题的人:

cc -g    -c -o cfs_clnt.o cfs_clnt.c
cc -g    -D_FILE_OFFSET_BITS=64 -c -o cfs_client.o cfs_client.c 
cc -g    -c -o cfs_xdr.o cfs_xdr.c
cc -g     -o cfs_client  cfs_clnt.o cfs_client.o cfs_xdr.o -lnsl -Wall `pkg-config fuse --cflags --libs`
cc -g    -c -o cfs_svc.o cfs_svc.c
cc -g    -c -o cfs_server.o cfs_server.c
cc -g     -o cfs_server  cfs_svc.o cfs_server.o cfs_xdr.o -lnsl

【讨论】:

以上是关于结合 fuse 和 rpc 来列出远程目录的主要内容,如果未能解决你的问题,请参考以下文章

RPC--HDFS节点间的沟通桥梁

女票的大杀器 —— RPC(远程过程调用)

架构师之路 — 分布式系统 — RPC 远程过程调用

架构师之路 — 分布式系统 — RPC 远程过程调用

在 python 的 RPC 世界中返回另一个远程对象的远程对象

UE4网络之(二) 远程调用函数(RPC)