开启NFS服务

来源:互联网 发布:网络流行词汇大全 编辑:程序博客网 时间:2024/05/16 14:09

1.开启NFS服务

设置好了需要导出的文件系统后,就可以开启NFS服务了。只有开启了NFS服务后,客户端才能挂载服务器端的文件系统。开启NFS服务的命令是 service nfs start,这条命令包含下列6条命令。

/sbin/service rpcsvcgssd start/usr/sbin/exportfs -r   rpc.rquotadrpc.nfsd 8rpc.mountd/sbin/service rpcidmapd condstart

rpcsvcgssd是和gss认证相关的一个服务,如果我们采用UNIX认证则可以不开启这个服务。rpc.rquotad是和磁盘配额相关的一个进程,这个进程也可以不开启。rpcidmapd是和用户名映射相关的一个服务,这个服务也可以不开启。因此,必须执行的命令是第2、4、5条。下面分别描述这三条命令做了什么工作。


2.exportfs

这条命令的主要作用是解析文件/etc/exports,结果存放到文件/var/lib/nfs/etab中。/etc/exports中包含了需要导出文件系统的选项,很多选项具有默认值,我们经常使用这些默认值,exportfs会将这些默认值填写到文件系统的选项中。比如下面这个文件系统

/tmp/nfs/  192.168.6.0/24(fsid=0,crossmnt,rw,no_root_squash,anonuid=500,anongid=500) 192.168.4.0/24(fsid=0,rw)

解析后的结果是

/tmp/nfs        192.168.6.0/24(rw,sync,wdelay,hide,crossmnt,secure,no_root_squash,no_all_squash,no_subtree_check,secure_locks,acl,fsid=0,anonuid=500,anongid=500)/tmp/nfs        192.168.4.0/24(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,fsid=0,anonuid=65534,anongid=65534)


3.rpc.nfsd

这是最主要的命令,开启了服务器端的NFS服务,NFS服务是一种RPC服务。简单来说,RPC是一种消息传输机制。客户端向服务器端发送RPC消息,服务器端对RPC消息进行处理,然后将处理结果返还给客户端。当我们在NFS文件系统中执行mkdir、ls、cat等操作时,客户端就会将这些操作转换成RPC消息传递给服务器端进行处理。NFS服务中定义了下列RPC消息。

#define NFSPROC_NULL            0#define NFSPROC_GETATTR         1#define NFSPROC_SETATTR         2#define NFSPROC_ROOT            3   // 去掉了#define NFSPROC_LOOKUP          4#define NFSPROC_READLINK        5#define NFSPROC_READ            6#define NFSPROC_WRITECACHE      7   // 去掉了#define NFSPROC_WRITE           8#define NFSPROC_CREATE          9#define NFSPROC_REMOVE          10#define NFSPROC_RENAME          11#define NFSPROC_LINK            12#define NFSPROC_SYMLINK         13#define NFSPROC_MKDIR           14#define NFSPROC_RMDIR           15#define NFSPROC_READDIR         16#define NFSPROC_STATFS          17

笼统来说,mkdir会转换成NFSPROC_MKDIR,ls转换成NFSPROC_READDIR,cat转换成NFSPROC_READ。服务器端开启NFS服务后,会创建一些内核线程,这些内核线程监听RPC消息。当RPC消息传到服务器端的时候,这些内核消息就会进行相应的处理。rpc.nfsd 8表示开起8个内核线程。


4.rpc.mountd

这条命令主要做了两件事情,第1件事情是开启了MOUNT服务。MOUNT服务也是一种RPC服务,当我们执行mount命令挂载NFS文件系统时,客户端通过MOUNT服务请求了服务器端的基本信息,主要是NFS文件系统根节点的文件句柄(以后的文章中会讲解文件句柄)和认证方式。但是NFSV4发生了变化,NFSV4将这项功能整合到NFS服务中了,因此NFSV4不需要开启MOUNT服务,但是仍然需要执行rpc.mountd命令,原因在rpc.mountd做的第2件事情。


rpc.mountd做的第2件事情就是解析了文件/var/lib/nfs/etab,将这个文件中的内容保存在内存中,当服务器端接收到NFS请求后需要从这个文件中查询NFS文件系统的信息。如果将这些信息保存在内存中则会加快查找速度。这个文件的解析是一件很繁琐但是不复杂的工作,主要涉及一些字符串解析函数、链表遍历函数和链表查找函数。因此这里就略过解析过程,直接贴出解析以后的结果了。


首先看与客户端地址类型相关的一个枚举变量。

enum {        MCL_FQDN = 0,                      // 表示通过域名访问        MCL_SUBNETWORK,                    // 表示通过IP地址访问        MCL_IPADDR = MCL_SUBNETWORK,       // 表示通过IP地址访问        MCL_WILDCARD,        MCL_NETGROUP,        MCL_ANONYMOUS,        MCL_GSS,        MCL_MAXTYPES};

这个变量表示了NFS中支持的客户端地址类型,这篇文章的例子中就是通过IP地址访问的,包含了192.168.6.0/24和192.168.4.0/24两个网段,这里将其称为两个认证域。每一个认证域用下面的数据结构表示。

typedef struct mclient {        struct mclient *        m_next;         // 指向下一个认证域        char *                  m_hostname;     // 认证域名称,如192.168.6.0/24        int                     m_type;         // 认证域类型,如MCL_IPADDR        int                     m_naddr;        union nfs_sockaddr      m_addrlist[NFSCLNT_ADDRMAX];        int                     m_exported;     /* exported to nfsd */        int                     m_count;} nfs_client;


按照认证域的类型,系统中所有的认证域保存在一个hash表中。

nfs_client      *clientlist[MCL_MAXTYPES] = { NULL, };

因此,服务器端认证域的保存方式如下:


表示文件系统的数据结构如下:

struct exportent {        char *          e_hostname;             char            e_path[NFS_MAXPATHLEN+1];            int             e_flags;              int             e_anonuid;        int             e_anongid;        int *           e_squids;        int             e_nsquids;        int *           e_sqgids;        int             e_nsqgids;        unsigned int    e_fsid;        char *          e_mountpoint;           int             e_fslocmethod;          char *          e_fslocdata;        char *          e_uuid;        struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];          unsigned int    e_ttl;};


这个结构中的各个字段就是导出文件系统时设置的各个选项。

这个数据结构是另外一个数据结构中的一个字段

typedef struct mexport {        struct mexport *        m_next;        struct mclient *        m_client;       // 这是认证域        struct exportent        m_export;       // 这是文件系统        int                     m_exported;     /* known to knfsd. -1 means not sure */        int                     m_xtabent  : 1, /* xtab entry exists */                                m_mayexport: 1, /* derived from xtabbed */                                m_changed  : 1, /* options (may) have changed */                                m_warned   : 1; /* warned about multiple exports                                                 * matching one client */} nfs_export;


因此,表示文件系统信息的数据结构是nfs_export,每个nfs_export结构表示一个导出的文件系统。在前面的例子中,我们导出了一个文件系统/tmp/nfs,但是设置了两个认证域192.168.6.0/24和192.168.4.0/24,因此系统中存在两个nfs_client结构,两个nfs_export结构。

nfs_export结构也是以hash表的形式存在的,不过这个hash表非常大,基本形式是下面这样的


首先,文件系统按照认证域类型分为了MCL_MAXTYPES个hash表,认证域相同的文件系统保存在同一个hash表中,每个hash表中包含1021个链表。当服务器接收到客户端的请求后,会查找这个大的hash表,判断客户端请求的是哪个文件系统,以及客户端对这个文件系统是否有相应的权限。如果权限满足,则处理这个请求。如果权限不满足,则拒绝这个请求。








原创粉丝点击