socket

在内核中,对socket实现了一种虚拟的文件系统(VFS):socketfs。和其它一般文件系统不同,它不能被mount,没有挂载点,而是通过一个静态变量来引用:
[ net/socket.c ]
static struct vfsmount *sock_mnt __read_mostly;
按照内核要求,定义一个结构来描述文件系统类型,然后在初始化时进行注册。

 * 包含文件系统名字:sockfs
 * 创建super_block函数:sockfs_mount
 * 删除super_block函数:kill_anon_super
 */
static struct file_system_type sock_fs_type = {
    .name =     "sockfs",
    .mount =    sockfs_mount,
    .kill_sb =  kill_anon_super,
};

sockfs_mount在安装文件系统(如:mount)时被调用:

/* 创建super_block函数
 */
static struct dentry *sockfs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
{
    /* 创建super block
     * 根目录名称为 socket:
     * 根目录对应的inode号为1
     */
    return mount_pseudo(fs_type, "socket:", &sockfs_ops, &sockfs_dentry_operations, SOCKFS_MAGIC);
}

在创建super block时,会将两个结构与其绑定,一个用于super block的操作,一个用于目录的操作:

/* contains the super block operations that sockfs supports.
 */
static const struct super_operations sockfs_ops = {
    .alloc_inode    = sock_alloc_inode,
    .destroy_inode  = sock_destroy_inode,
    .statfs     = simple_statfs,
};

static const struct dentry_operations sockfs_dentry_operations = {
    .d_dname  = sockfs_dname,
};

当新建一个socket时,会有一个文件与其对应,这个文件的名称由sockfs_dname来创建:

/*
 * sockfs_dname() is called from d_path().
 */
static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
{
    /* ls -l /proc/1929/fd
     * lrwx------ 1 root root 64 2015-04-07 10:50 93 -> socket:[33107]
     */
    return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]", dentry->d_inode->i_ino);
}

有了文件名称(文件名称都保存在目录文件中),还要创建一个对应的inode,这样才能对其进行读写操作。为此,内核提供了一个缓冲池:

/* socket的inode节点的缓冲池
 */
static struct kmem_cache *sock_inode_cachep __read_mostly;
/* 初始化缓冲池,缓冲池中的节点为socket_alloc
 */
static int init_inodecache(void)
{
    sock_inode_cachep = kmem_cache_create("sock_inode_cache",
                          sizeof(struct socket_alloc),
                          0,
                          (SLAB_HWCACHE_ALIGN |
                           SLAB_RECLAIM_ACCOUNT |
                           SLAB_MEM_SPREAD),
                          init_once);
    if (sock_inode_cachep == NULL)
        return -ENOMEM;
    return 0;
}
static void init_once(void *foo)
{
    struct socket_alloc *ei = (struct socket_alloc *)foo;

    inode_init_once(&ei->vfs_inode);
}
struct socket_alloc {
    struct socket socket;
    struct inode vfs_inode;
};

然后来看分配inode的函数:

static struct inode *sock_alloc_inode(struct super_block *sb)
{
    struct socket_alloc *ei;
    struct socket_wq *wq;

    /* 从缓冲池中分配一个socket_alloc结构
     */
    ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
    if (!ei)
        return NULL;
    /* 分配等待队列结构
     * 初始化后,将其赋值给ei->socket.wq
     */
    wq = kmalloc(sizeof(*wq), GFP_KERNEL);
    if (!wq) {
        kmem_cache_free(sock_inode_cachep, ei);
        return NULL;
    }
    init_waitqueue_head(&wq->wait);
    wq->fasync_list = NULL;
    RCU_INIT_POINTER(ei->socket.wq, wq);

    /* 初始化ei->socket
     */
    ei->socket.state = SS_UNCONNECTED;
    ei->socket.flags = 0;
    ei->socket.ops = NULL;
    ei->socket.sk = NULL;
    ei->socket.file = 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值