The high-level version of how mounting NFS filesystems works
For reasons that are going to become apparent soon, I need to explain how NFS mounting works.
NFS servers (in the code and protocol sense) just talk NFS, which is to say that you give them an NFS filehandle and tell them what operation you want to do with it and they give you a reply. One of those operations is to look up a name in a directory and give you its filehandle, which is the basic building block that lets a client traverse a filesystem's directory hierarchy.
Thus, at a conceptual level you mount an NFS filesystem by acquiring the
filehandle of its root directory (and then remembering it locally). The
NFS protocol has no mechanism for doing this, since all NFS operations
start with the filehandle; instead, the job is delegated to an entirely
separate protocol, the NFS mount protocol ('
this protocol on the NFS server is traditionally done by a separate
user-level program, the (NFS) mount daemon, and some associated daemons.
(It needs more than one daemon because of extra generality. NFS mounting is based on Sun RPC, and Sun RPC requires a bootstrapping process; first you ask the RPC portmapper on which port you can find whatever handles the mountd protocol, and then you go talk to that port to do the actual work. This avoids having to ask IANA for a bunch of port assignments, and back in 1986 or so no one had even started thinking about firewalls so the idea that services might wind up on randomly chosen TCP ports did not fill sysadmins with screaming nightmares. But I digress.)
Traditionally, clients also implement the NFS mount protocol in a
separate user-level program (sometimes directly including it in
sometimes making it a separate internal program that
for you). That program talks RPC to the NFS mount daemon, basically
giving it a path and getting back an NFS filehandle; it then takes that
filehandle and passes it to the kernel somehow (along with all of the
other information about the mount that the kernel needs), where the
kernel NFS client code takes over.
While this may seem peculiar, the advantage of this split is that
neither the client nor the server kernels need to have all sorts of
complicated code to do things like hostname lookups, RPC portmapping,
/etc/exports, and so on, all of which is much easier and more
flexible when done in user level code.
(Having a separate NFS mount protocol also keeps the NFS protocol itself simpler and more regular.)