文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>socket实现分析series(3)

socket实现分析series(3)

时间:2010-08-26  来源:mtloveft

  声明:本文为原创 #####请转贴时保留以下内容###### 作者:GTT 本文档归属http://oldtown.cublog.cn/.转载请注明出处! 请提出宝贵意见Mail:[email protected] 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创建过程的流程图请参看 http://blog.chinaunix.net/u3/114767/showart_2277297.html   当时就想写详细些,一直没时间,这次想完整的介绍。        



相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载