LINUX SOCKFS文件系统分析之四 socket相关的系统调用简要介绍

以上几篇文章介绍了sockfs的注册及挂载、相关数据结构之间的关联介绍、socket创建过程,本小

节主要介绍socket相关的系统调用,并以tcp协议为例,分析tcp协议相关的处理接口是如何与这些系统调用关联起来的。

 

针对socket而言,其相关的系统调用有socket、listen、accept、shutdown、connect、bind、

recvmsg、getsockname、sendmsg、send、setsockopt、getsockopt等,此处我们以setsockopt进行分析说明,其他的系统调用也是类似的。

 

 

setsockopt接口分析

该接口主要是设置socket相关的一些属性参数,针对tcp协议而言,我们可以设置tcp保活机制相关的参数(TCP_KEEPIDLE、TCP_KEEPINTVL、TCP_KEEPCNT)等。

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

该接口主要包括两个大的方向的内容:

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

2.根据本次设置的opt类型,选择对应的设置接口:

  1. 若为socket通用的opt类型(即opt类型为SOL_SOCKET),则调用sock_setsockopt进行处理;
  2. 若设置的opt类型为具体socket类型(SOCK_STREAM/SOCK_DGRAM等)相关联的,调用socket类型具体的操作处理接口(即由struct proto_ops类型定义的指针变量)。

 

 

以上即为setsockopt处理的流程以及主要功能点,针对sockfd_lookup_light而言,其通过fd获取

文件描述符,再通过文件描述符获取socket,该接口的定义相对简单,如上流程图所示,不再展开细说。

而针对opt的处理接口,存在两个处理接口,针对通用的处理接口sock_setsockopt,主要是设置

socket相关的通用动作,本文也不再细说。本次主要说明下socket类型相关的通用动作的设置。

const struct proto_ops inet_stream_ops = {

…

.setsockopt           = sock_common_setsockopt,

.getsockopt           = sock_common_getsockopt,

…

};

 

此处我们以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 套接字文件系统(sockfs)分析之三 socket fd创建的过程》,关于struct proto、struct proto_ops结构体的关联,请参考文章《LINUX 套接字文件系统(sockfs)分析之二 相关结构体分析》),该变量的定义如下,因此其setsockopt接口为tcp_setsockopt,tcp_setsockopt的定义如下所示,主要调用do_tcp_setsockopt接口实现tcp相关动作的操作,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上,需要了解的请点击https://blog.csdn.net/lickylin)。

 

原文链接:加载失败,请重新获取