Chinaunix首页 | 论坛 | 博客
  • 博客访问: 47337
  • 博文数量: 6
  • 博客积分: 1612
  • 博客等级: 上尉
  • 技术积分: 80
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-11 10:21
文章分类
文章存档

2009年(6)

分类: LINUX

2009-10-14 20:08:36

    关于socket的调用过程简单说下,自己在这里犯过错误
    虽然有sys_socket但是unistd.h里面并没有__NR_socket因为基本上所有socket的调用都是通过socketcall一个接口完成的。以后就不写socketcall了,直接进入主题

asmlinkage long sys_socket(int family, int type, int protocol)
{
    int retval;
    struct socket *sock;
    int flags;

    /* Check the SOCK_* constants for consistency. */
    BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
    BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
    BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
    BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);

     //SOCK_TYPE_MASK=0xf,也就是说SOCK_STREAM,SOCK_DGRAM等最多有15个
    flags = type & ~SOCK_TYPE_MASK;
    //如果除了这两个标志外还包含其他标志则EINVAL。

    //从2.6.27开始type可以支持SOCK_CLOEXEC和SOCK_NONBLOCK,见socket(2)
    if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
        return -EINVAL;
    type &= SOCK_TYPE_MASK;

    if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
        flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;

    retval = sock_create(family, type, protocol, &sock); //后面讲解
    if (retval < 0)
        goto out;

    //将所得到的socket结构映射到一个fd上,然后返回这个fd;
    retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
    if (retval < 0)
        goto out_release;

out:
    /* It may be already another descriptor 8) Not kernel problem. */
    return retval;

out_release:
    sock_release(sock);
    return retval;
}

sys_socket没什么东西,接下来看sock_create


 

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;

    //过去inet族协议的SOCK_PACKET套接字现在已改变为AF_PACKET族,

    //为了兼容过去的代码作一些检测
    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; //这里将SOCK_STREAM付给了socket->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) //net_families在tcp数据结构中有说明,实际上重要的字段只有create,在inet协议族它等于inet_create

        request_module("net-pf-%d", family);
#endif

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

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

    rcu_read_unlock();

    //inet_create

    err = pf->create(net, sock, protocol);
    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;
}


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