Chinaunix首页 | 论坛 | 博客
  • 博客访问: 643987
  • 博文数量: 155
  • 博客积分: 5688
  • 博客等级: 大校
  • 技术积分: 2134
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-15 15:12
文章分类

全部博文(155)

文章存档

2011年(58)

2010年(97)

分类: 系统运维

2010-08-26 22:20:01

 
声明:本文为原创
#####请转贴时保留以下内容######
作者GTT
本文档归属http://oldtown.cublog.cn/.转载请注明出处!
请提出宝贵意见Mail:mtloveft@hotmail.com
Linux Version:2.6.33
提示本文是关于linux 如何实现socket 通信的介绍
 
SYS_SOCKET中sock_create 方法代码如下

int sock_create(int family, int type, int protocol, struct socket **res)
{
    return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
}

 
继续
 

static int __sock_create(struct net *net, int family, int type, int protocol, struct socket **res, int kern)
{
    int err;
    struct socket *sock;
    const struct net_proto_family *pf;

    /* Check protocol is in range */
    if (family < 0 || family >= NPROTO) return -EAFNOSUPPORT;
    if (type < 0 || type >= SOCK_MAX) return -EINVAL;

    /* Compatibility. This uglymoron is moved from INET layer to here to avoid deadlock in module load. */
    if (family == PF_INET && type == SOCK_PACKET) {
        static int warned;
        if (!warned) {
            warned = 1;
            printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
        }
        family = PF_PACKET;
    }

    err = security_socket_create(family, type, protocol, kern);
    if (err) return err;

    
/*
     * Allocate the socket and allow the family to set things up. if
     * the protocol is 0, the family is instructed to select an appropriate default.
     */

    sock = sock_alloc();
    if (!sock) {
        if (net_ratelimit()) printk(KERN_WARNING "socket: no more sockets\n");
        return -ENFILE; /* Not exactly a match, but its the closest posix thing */
    }

    sock->type = type;

#ifdef CONFIG_MODULES
    
/* Attempt to load a protocol module if the find failed.
     *
     * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
     * requested real, full-featured networking support upon configuration.
     * Otherwise module support will break!
     */

    if (net_families[family] == NULL) request_module("net-pf-%d", family);
#endif

    rcu_read_lock();
    pf = rcu_dereference(net_families[family]);
    err = -EAFNOSUPPORT;
    if (!pf) goto out_release;

    
/*
     * We will call the ->create function, that possibly is in a loadable
     * module, so we have to bump that loadable module refcnt first.
     */

    if (!try_module_get(pf->owner)) goto out_release;

    /* Now protected by module ref count */
    rcu_read_unlock();

    err = pf->create(net, sock, protocol, kern);
    if (err < 0) goto out_module_put;

    
/*
     * Now to bump the refcnt of the [loadable] module that owns this
     * socket at sock_release time we decrement its refcnt.
     */

    if (!try_module_get(sock->ops->owner)) goto out_module_busy;

    
/*
     * Now that we're done with the ->create function, the [loadable]
     * module can have its refcnt decremented
     */

    module_put(pf->owner);
    err = security_socket_post_create(sock, family, type, protocol, kern);
    if (err) goto out_sock_release;
    *res = sock;

    return 0;

out_module_busy:
    err = -EAFNOSUPPORT;
out_module_put:
    sock->ops = NULL;
    module_put(pf->owner);
out_sock_release:
    sock_release(sock);
    return err;

out_release:
    rcu_read_unlock();
    goto out_sock_release;
}

 
 
协议族数组net_families的定义如下

static const struct net_proto_family *net_families[NPROTO] __read_mostly;

 
协议族注册方法如下

/**
 * sock_register - add a socket protocol handler
 * @ops: description of protocol
 *
 * This function is called by a protocol handler that wants to
 * advertise its address family, and have it linked into the
 * socket interface. The value ops->family coresponds to the
 * socket system call protocol family.
 */

int sock_register(const struct net_proto_family *ops)
{
    int err;

    if (ops->family >= NPROTO) {
        printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, NPROTO);
        return -ENOBUFS;
    }

    spin_lock(&net_family_lock);
    if (net_families[ops->family]) err = -EEXIST;
    else {
        net_families[ops->family] = ops;
        err = 0;
    }
    spin_unlock(&net_family_lock);

    printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family);
    return err;
}

 
而在linux里所有的协议族定义如下
 
PF_INET就是ipv4网络。
 
当然也是在kernel初始化的时候就注册了inet的net_proto_family了。
下篇文章介绍inet的初始化。
 
关于socket创建过程的流程图请参看
 
当时就想写详细些,一直没时间,这次想完整的介绍。
 
 
 
 




阅读(1263) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~