注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

unix socket简介  

2012-09-18 00:35:25|  分类: Linux内核 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、unix socket
其实这种类型的套接口我用的不是很多,只是感觉比较有意思。也就是机制本身的思想对于它对于我工作上的实用性更加的高,所以始终想看一下机制的一些实现。通常我们不常用这种机制,但是对于大部分的Linux发行版本,可以比较经常的见到这种类型的套接口。其实简单来说,例如,在我使用的fedora core发行版本中,通过netstat可以看到系统中的unix套接口的数量还是相当的多的。
总结原因,可能是它比较好的适合了"服务器/客户端"的通讯模型。在一个系统内部,同样存在着客户端和服务器的模型,例如我们可以认为一个系统剪切板就是一个服务器,服务器和客户端是一个一对多的关系。这里的一对多不仅要关注其中的“多”,也需要关注其中的“一”。其它的pipe、fifo、msgqueue也可以提供很好的进程间通讯,它是它们的缺点是不能保证一对多中的“一”。对于同一个资源,前面说的几种都可以被多个进程使用。而unix socket可以保证一个本地的资源只有一个人来使用,而这个人就是对该socket执行了bind的进程。和TCP协议一样,一个unix的socket只能被执行一次bind操作,从而在机制上保证了服务器的唯一性。
另外,在mysql数据库的命令行程序mysql和mysqld的通讯中,如果没有指定端口号,同样是使用unix socket进行通讯。
二、bind时创建
由于unix socket是在本地运行的一个服务器端口,所以它的地址是一个系统路径,这个路径其实是真真切切对应一个路径所在文件系统中的目录项,和普通文件一样,新创建的socket也有自己的inode节点,并且这个节点同样是在所在文件系统的inode区中占有一个inode节点。
unix_bind

        /*
         * All right, let's create it.
         */
        mode = S_IFSOCK |
               (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
        err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
        if (err)如果出错,直接返回。这个出错包括了文件已经存在这种错误
            goto out_mknod_dput;
以我们最为常见的ext2文件系统为例,其创建一个节点的代码为
static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev)
{
    struct inode * inode;
    int err;

    if (!new_valid_dev(rdev))
        return -EINVAL;

    inode = ext2_new_inode (dir, mode); 也就是这个节点是实实在在分配了的
……
}
三、节点何时删除
这种创建比较持久,但是持久的东西消除就比较麻烦,就像塑料购物袋一样,非常简单便捷,但是缺点就是不容易销毁,所以污染环境。同样滴。对于一个unix socket,它每次创建都通过在文件系统上真正创建一个文件来保证自己的先进性,那么这个文件将会在何时删除呢?事实上这种文件是一旦创建就一直存在的,和普通文件一样,除非手动删除(unlink系统调用)。从内核代码来看,对于套接口的关闭并没有区分客户端和服务器,都是使用相同的unix_release(该接口在文件执行close的时候由系统调用)。
static int unix_release_sock (struct sock *sk, int embrion)
{
……
    dentry         = u->dentry;
    u->dentry    = NULL;
……
    if (dentry) {
        dput(dentry);
        mntput(mnt);
    }
……
}
回过头来看看client在执行bind的时候,其中执行的操作
……
    if (otheru->dentry) {
        newu->dentry    = dget(otheru->dentry); 这是增加了文件路径引用的次数,和release对应,每个套接口在关闭的时候会减少节点的引用次数,当引用次数这里引用次数的减少并不会导致文件被删除,而只是会说明文件在内存中的结构不存在,文件删除是通过inode中的nlink值减低为零的时候才进行删除。这也意味着如果一个进程还在使用这个套接口,即使通过rm删除文件,它在内存中依然是存在的
        newu->mnt    = mntget(otheru->mnt);
    }
所以当一个socket创建之后,需要通过手动的删除文件该文件才能够被删除。由于不常用unix套接口,不清楚工程中是如何处理和利用这种特征的。
四、netstat看unix套接口
通过netstat可以看到一些套接口并没有显示路径名。我当时看到的原因是由于权限问题,当时使用的是非root用户。netstat的实现原理是通过/proc/net/unix文件得到系统中所有unix套接口的inode,然后扫描/proc/$PID/ls文件夹下所有文件的地址。由于一些unix套接口是root用户创建的,netstat以非root用户执行的时候,没有root文件夹的执行权限(也就是文件夹的搜索权限),所以无法列出这些inode的路径名。
  评论这张
 
阅读(966)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017