由於涉及到網路,和檔案系統的讀寫資料介面比較起來,使用網路收發資料的介面最抽象的概念就是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;