【每日一题】sockfs的注册及相关数据结构之间的关联介绍

以上文章介绍了sockfs的注册和挂载,相关数据结构之间的关联,以及socket创建的过程。本节主要介绍socket相关的系统调用,并以tcp协议为例,分析tcp协议相关的处理接口是如何与这些系统调用关联的。

对于socket,其相关的系统调用包括socket、listen、accept、shutdown、connect、bind、recvmsg、getsockname、sendmsg、send、setsockopt、getsockopt等,这里我们使用setsockopt进行分析和说明,其他系统调用有类似。

setsockopt接口分析

这个接口主要是设置一些socket相关的opt参数。对于tcp协议,我们可以设置tcp keep-alive机制相关的参数(TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNT)等。

首先,我们来看看setsockopt的定义。该接口的处理流程如下

这个界面主要包括两大方向的内容:

1.根据fd获取struct socket类型的指针(通过调用sockfd_lookup_light);

2.根据本次设置的opt type,选择对应的设置界面:

如果是socket的通用opt类型(即opt类型为SOL_SOCKET),调用sock_setsockopt进行处理;如果设置的opt type关联了特定的socket类型(SOCK_STREAM/SOCK_DGRAM等)应用编程接口和套接字应用编程接口和套接字,则调用socket类型的具体操作处理一个接口(即struct proto_ops类型定义的指针变量)。

以上是setsockopt处理的流程和主要功能点。对于sockfd_lookup_light,它通过fd获取文件描述符,然后通过文件描述符获取socket。这个接口的定义比较简单。进一步展开。

opt的处理接口,有两个处理接口。对于通用处理接口sock_setsockopt,主要设置与sockets相关的通用动作,本文不再赘述。这次主要介绍socket类型相关的常用action的设置。

这里我们以tcp协议为例。当我们创建一个tcp协议链接时,socket类型是SOCK_STREAM(该类型的struct proto_ops类型变量的定义如上),所以sock->ops->setsockopt调用的接口是sock_common_setsockopt。接口的定义如下,即调用具体协议相关的setsockopt。接下来我们确认tcp协议的setsockopt是哪个函数。

int sock_common_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
 struct sock *sk = sock->sk;
 return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);
}

对于tcp协议,我们知道它的sk_proto是tcp_prot(关于sk->sk_prot的赋值过程请参考文章《Linux socket文件系统(sockfs)解析第三个socket fd创建过程》,关于struct proto和struct proto_ops结构体的关联请参考文章《LINUX Socket File System(sockfs)II相关结构体分析》,该变量的定义如下,所以它的setsockopt接口为tcp_setsockopt,而tcp_setsockopt的定义如下图所示,主要调用do_tcp_setsockopt接口实现tcp相关action的操作,do_tcp_setsockopt实现了对TCP_MAXSEG、TCP_NODELAY、TCP_THIN_LINEAR_TIMEOUTS、TCP_THIN_DUPACK、TCP_REPAIR、TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNT等opt类型的支持等,因为do_tcp_setsockopt主要是根据opt的类型来的。设置操作,本文不再展开界面分析。

struct proto tcp_prot = {
…
.setsockopt = tcp_setsockopt,
.getsockopt = tcp_getsockopt,
…
};
int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
unsigned int optlen)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
if (level != SOL_TCP)
return icsk->icsk_af_ops->setsockopt(sk, level, optname,
optval, optlen);
return do_tcp_setsockopt(sk, level, optname, optval, optlen);
}

以上就是本章的全部内容,主要讲解socket系统调用的处理过程。本文也是socketfs介绍的最后一部分。本来打算分析一下socket中ioctl的处理流程和ifconfig if up/down的处理流程,但是这些内容只需要真正做协议栈开发或者网络开发的人掌握,对用户来说意义不大掌握LINUX内核VFS原理的人,这部分内容我就不介绍了(我之前分析过linux内核协议栈。和netfilter相关内容,相关文章在csdn上,需要了解的请点击) .

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论