Skip to content

Socket 系统调用

1. 模块架构

1.1 功能概述

Socket 系统调用是用户进程与内核网络栈交互的入口点,提供创建、连接、绑定、监听等操作。

1.2 关键源文件

文件作用
net/socket.cSocket 核心实现
net/scm.cSocket Control Message
include/linux/net.hSocket 定义

2. Socket 创建

2.1 sys_socket()

c
// net/socket.c:770
int __sys_socket(int family, int type, int protocol)
{
    int fd;
    struct socket *sock;

    // 1. 创建 socket
    sock = sock_create(family, type, protocol, &sock);
    if (IS_ERR(sock))
        return PTR_ERR(sock);

    // 2. 分配文件描述符
    fd = get_unused_fd_flags(O_RDWR);
    if (fd < 0) {
        sock_release(sock);
        return fd;
    }

    // 3. 关联到文件描述符
    fd_install(fd, sock->file);

    return fd;
}

2.2 sock_create()

c
// net/socket.c:450
int sock_create(int family, int type, int protocol, struct socket **res)
{
    return __sock_create(current->nsproxy->net_ns, family, type,
                         protocol, res, 0);
}

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

    // 1. 分配 socket
    sock = sock_alloc();
    if (!sock)
        return -ENOMEM;

    // 2. 初始化
    sock->family = family;
    sock->type = type;
    sock->protocol = protocol;

    // 3. 调用协议族特定创建函数
    pf = rcu_dereference(net_families[family]);
    err = pf->create(sock, protocol);

    *res = sock;
    return err;
}

3. 绑定和监听

3.1 sys_bind()

c
// net/socket.c:850
int __sys_bind(int fd, struct sockaddr *addr, int addrlen)
{
    struct socket *sock;
    struct sockaddr_storage address;

    // 获取 socket
    sock = sockfd_lookup(fd, &err);
    if (sock) {
        // 复制地址
        err = move_addr_to_kernel(addr, addrlen, &address);
        if (!err)
            // 调用 socket->ops->bind
            err = sock->ops->bind(sock, (struct sockaddr *)&address,
                                  addrlen);
        fput(sock->file);
    }
    return err;
}

3.2 sys_listen()

c
// net/socket.c:920
int __sys_listen(int fd, int backlog)
{
    struct socket *sock;
    int err;

    sock = sockfd_lookup(fd, &err);
    if (sock) {
        // 调用 socket->ops->listen
        err = sock->ops->listen(sock, backlog);
        fput(sock->file);
    }
    return err;
}

4. 连接

4.1 sys_connect()

c
// net/socket.c:890
int __sys_connect(int fd, struct sockaddr *addr, int addrlen)
{
    struct socket *sock;
    struct sockaddr_storage address;

    sock = sockfd_lookup(fd, &err);
    if (sock) {
        err = move_addr_to_kernel(addr, addrlen, &address);
        if (!err)
            err = sock->ops->connect(sock,
                                    (struct sockaddr *)&address,
                                    addrlen, 0);
        fput(sock->file);
    }
    return err;
}

4.2 accept()

c
// net/socket.c:960
int __sys_accept4(int fd, struct sockaddr *u_peer_sockaddr,
                  int *u_peer_addrlen, int flags)
{
    struct socket *sock, *newsock;
    struct sockaddr_storage address;
    int err;

    sock = sockfd_lookup(fd, &err);
    if (sock) {
        // 从 backlog 取出或等待新连接
        err = sock->ops->accept(sock, &newsock, flags);
        if (!err) {
            // 分配新文件描述符
            newfd = get_unused_fd_flags(flags);
            if (newfd >= 0)
                fd_install(newfd, newsock->file);
            else
                sock_release(newsock);
        }
        fput(sock->file);
    }
    return err;
}

5. 发送/接收

5.1 sys_sendmsg()

c
// net/socket.c:1280
int __sys_sendmsg(int fd, struct msghdr *msg, unsigned int flags)
{
    struct socket *sock;
    struct iovec iov;
    struct sockaddr_storage address;

    sock = sockfd_lookup(fd, &err);
    if (sock) {
        // 复制 msghdr 到内核
        err = copy_msghdr_from_user(&msg_sys, msg, &iov, &address);

        if (!err)
            err = sock_sendmsg(sock, &msg_sys);
        fput(sock->file);
    }
    return err;
}

5.2 sys_recvmsg()

c
// net/socket.c:1320
int __sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
{
    struct socket *sock;
    struct msghdr msg_sys;
    struct iovec iov;

    sock = sockfd_lookup(fd, &err);
    if (sock) {
        // 初始化 msg_sys
        err = copy_msghdr_from_user(&msg_sys, msg, &iov, NULL);

        if (!err)
            err = sock_recvmsg(sock, &msg_sys, flags);
        fput(sock->file);
    }
    return err;
}

6. close()

c
// net/socket.c:680
int sock_close(struct inode *inode, struct file *filp)
{
    struct socket *sock;

    sock = filp->private_data;
    sock_release(sock);
    return 0;
}

void sock_release(struct socket *sock)
{
    // 调用协议特定清理
    if (sock->ops)
        sock->ops->release(sock);

    // 释放 socket
    sock_no_release(sock);
}

7. socket 文件操作

c
// net/socket.c:180
static const struct proto_ops socket_ops = {
    .family = PF_UNSPEC,
    .owner = THIS_MODULE,
    .release = sock_close,
    .bind = sock_bind,
    .connect = sock_connect,
    .socketpair = sock_socketpair,
    .accept = sock_accept,
    .getname = sock_getname,
    .poll = sock_poll,
    .ioctl = sock_ioctl,
    .listen = sock_listen,
    .shutdown = sock_shutdown,
    .sendmsg = sock_sendmsg,
    .recvmsg = sock_recvmsg,
    .sendpage = sock_sendpage,
    .set_sockopt = sock_setsockopt,
    .get_sockopt = sock_getsockopt,
};

基于 VitePress 构建