由于涉及到网络,和文件系统的读写数据接口比较起来,使用网络收发数据的接口最抽象的概念就是socket。网络收发数据的接口是BSD定义的一套接口,文件系统是open与close的对应。
首先需要了解的是网络文件系统的初始化:
static int __init sock_init(void)
{
/*
* Initialize sock SLAB cache.
*/
sk_init();
/*
* Initialize skbuff SLAB cache
*/
skb_init();
/*
* */
init_inodecache();
register_filesystem(&sock_fs_type);
sock_mnt = kern_mount(&sock_fs_type);
/* The real protocol initialization is performed in later initcalls.
*/
#ifdef CONFIG_NETFILTER
netfilter_init();
#endif
return 0;
}
core_initcall(sock_init); /* early initcall */
core_initcall可以查阅相关资料,流程就是机器在启动初始化时调用了sock_init函数。
网络文件系统是特殊的,文件系统的挂载没有安装常规文件系统的做法来实现:
1、首先没有查找全局文件系统链表获得文件系统类型
2、网络文件系统类型并没有真正挂载到VFS的目录树中,而是通过全局变量来使用。即:
static struct vfsmount *sock_mnt __read_mostly;//保存为全局变量,需要时直接使用
sock_mnt = kern_mount(&sock_fs_type);
也就是说这个文件系统是无法通过常规的文件系统接口来使用的,更无法通过cd、ls等命令来查看了。
那么文件系统的注册还需要吗?就网络文件系统本身的功能来说是不需要的,但是需要保证不能有其他进程再重复的挂载网络文件系统。
register_filesystem(&sock_fs_type);
文件系统的注册保证网络文件系统已经增加到全局文件系统链表中。
文件系统挂载过程可以查看相关源代码。重点说明代表网络文件系统类型的sock_fs_type结构:
static struct file_system_type sock_fs_type = {
.name = "sockfs",
.get_sb = sockfs_get_sb,
.kill_sb = kill_anon_super,
};
继续:
static int sockfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data,
struct vfsmount *mnt)
{
return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,mnt);
}
在得到文件系统超级块的过程中,get_sb_pseudo通过
s->s_op = ops ? ops : &simple_super_operations;
把sockfs_ops赋值给s->s_op。
继续:
static const struct super_operations sockfs_ops = {
.alloc_inode = sock_alloc_inode,
.destroy_inode =sock_destroy_inode,
.statfs = simple_statfs,
};
继续:
static struct inode *sock_alloc_inode(struct super_block *sb)
{
struct socket_alloc *ei;
ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
if (!ei)
return NULL;
init_waitqueue_head(&ei->socket.wait);
ei->socket.fasync_list = NULL;
ei->socket.state = SS_UNCONNECTED;
ei->socket.flags = 0;
ei->socket.ops = NULL;
ei->socket.sk = NULL;
ei->socket.file = NULL;
return &ei->vfs_inode;
}
总结起来是三个全局变量了:sock_mnt,sock_fs_type,sockfs_ops。
sock_inode_cachep是sock_init中的 init_inodecache()声明的全局变量:
static struct kmem_cache *sock_inode_cachep __read_mostly;