gpt4 book ai didi

c - 为什么sctp_inet_listen的第一个参数是struct socket*而不是int

转载 作者:行者123 更新时间:2023-12-03 12:02:09 25 4
gpt4 key购买 nike

我想研究内核网络部分的源码,了解内核的网络部分是如何工作的。但是当我查看listen函数时,发现了上面的问题。用man看listen函数的第一个参数是int。
int 听(int sockfd,int backlog);
但是在 https://github.com/torvalds/linux ,sctp_inet_listen函数的第一个参数是struct socket*,在protocol.c中我们知道listen是sctp_inet_listen的函数指针

static const struct proto_ops inet_seqpacket_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release, /* Needs to be wrapped... */
.bind = inet_bind,
.connect = sctp_inet_connect,
.socketpair = sock_no_socketpair,
.accept = inet_accept,
.getname = inet_getname, /* Semantics are different. */
.poll = sctp_poll,
.ioctl = inet_ioctl,
.gettstamp = sock_gettstamp,
.listen = sctp_inet_listen,
.shutdown = inet_shutdown, /* Looks harmless. */
.setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem */
.getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg,
.mmap = sock_no_mmap,
.sendpage = sock_no_sendpage,
};
int sctp_inet_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
struct sctp_endpoint *ep = sctp_sk(sk)->ep;
int err = -EINVAL;

if (unlikely(backlog < 0))
return err;

lock_sock(sk);

/* Peeled-off sockets are not allowed to listen(). */
if (sctp_style(sk, UDP_HIGH_BANDWIDTH))
goto out;

if (sock->state != SS_UNCONNECTED)
goto out;

if (!sctp_sstate(sk, LISTENING) && !sctp_sstate(sk, CLOSED))
goto out;

/* If backlog is zero, disable listening. */
if (!backlog) {
if (sctp_sstate(sk, CLOSED))
goto out;

err = 0;
sctp_unhash_endpoint(ep);
sk->sk_state = SCTP_SS_CLOSED;
if (sk->sk_reuse || sctp_sk(sk)->reuse)
sctp_sk(sk)->bind_hash->fastreuse = 1;
goto out;
}

/* If we are already listening, just update the backlog */
if (sctp_sstate(sk, LISTENING))
WRITE_ONCE(sk->sk_max_ack_backlog, backlog);
else {
err = sctp_listen_start(sk, backlog);
if (err)
goto out;
}

err = 0;
out:
release_sock(sk);
return err;
}

最佳答案

在 Linux 中,C 库函数 listen(fd,backlog) 对应于具有相同原型(prototype)的系统调用 (SYS_listen)。此系统调用在 net/socket.c 中实现(见 SYSCALL_DEFINE2(listen, int, fd, int, backlog))。它调用 net/socket.c:__sys_listen()。
net/socket.c:__sys_listen() 通过查找文件描述表条目 struct socket 来查找套接字描述(类型为 fd) ,并进行基本的检查和簿记工作。struct socket结构包含成员 ops ,它是指向 struct proto_ops 的指针.这是一组函数指针,因此可以在同一接口(interface)中支持不同类型的套接字(例如,Unix 域套接字或 IP 套接字)。 (基本上,每种套接字类型都定义了自己的 proto_ops。)
net/socket.c:__sys_listen() 获取 listen该集合的函数指针,并调用它,以便不同的套接字类型可以实现自己的“监听”功能。因为已经查找了文件描述符,并转换为指向套接字描述的指针,所以传递了该指针(而不是文件描述符)。 (使用函数的所有文件/套接字描述符都使用相同或非常相似的接口(interface)。)
这里要实现的核心点是文件描述符编号只是对特定于进程的文件描述引用表的索引。对于套接字,该引用的类型为 struct sock * . (文件描述表是内核内部的,通常称为文件表;特定于进程的引用表通常称为文件描述符表;文件描述符是文件描述符表的索引。如果你发现这个令人困惑,请阅读例如 Wikipedia File descriptor 文章了解更多详细信息。)

关于c - 为什么sctp_inet_listen的第一个参数是struct socket*而不是int,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64830772/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com