linux 套接口文件_LINUX 套接字文件系统(sockfs)分析之二 相关结构体分析

上一篇文章说明了socketfs的注册以及挂载,本小节主要说明socketfs相关的结构体,这些结构体涉及socket的创建以及与vfs之间的关联等。

对于网络协议簇而言,包括ax25协议簇、inet4协议簇、inet6协议簇、ipx协议簇等,而每一个协议簇中又包含多个协议,以inet4协议簇为例,又包含ipv4、tcp、udp、icmp等协议。

而针对网络协议簇与网络协议之间的关系,linux sockfs的架构也按此进行了划分。

针对sockfs,其也兼容VFS架构,但相比于普通文件及设备文件而言,也有不同,针对socket文件的操作,linux提供了一系列专用的系统调用接口,包括socket、listen、shutdown、connect、bind、accept、recvmsg、getsockname、getpeername、sendmsg、socketpair、send、setsockopt、getsockopt、recvfrom、sendto等接口,使用这些接口可实现上述所说协议簇中的各协议的socket通信。

针对sockfs而言,其系统调用socket与open实现的功能类似,不同的是socket fd中增加了针对网络协议簇相关的一套框架,用于实现对上述所说的packet协议簇、ipc socket、netlink、ipv4、ipv6等协议的socket通信。这些结构体包括struct sock、struct socket、struct net_proto、struct inet_protosw、struct proto、struct proto_ops,首先我们分析这些结构体的定义以及这些结构体的关联,待我们理解这些结构体之后,再分析具体的实现接口。

在分析每一个结构体之前,我们先看下这些结构体有什么关联,先从整体上了解这些结构体,然后再分而治之。

struct inet_protosw、struct proto、struct proto_ops、struct socket、struct sock、struct file之间的关联

针对这几个结构体以及文件描述符结构体struct file,下图便是这几个结构体的关联。这些结构体的主要关联有:

  1. 将vfs与sockfs进行了关联;
  2. 将socket与具体协议处理接口、具体的socket type处理接口完成了关联操作;
  3. 在af_inet4中,存在struct inet_protosw与socket类型对应的操作接口、具体协议类型对应的操作接口的关联,实现了通过socket即可调用具体协议类型对应处理接口,处理链接创建与删除、数据收发等操作。
e8ceab3a58d6060aa38e52a85fadd4b7.png

介绍完结构体之间的联系后,我们再逐个分析每一个结构体的定义。

1.struct socket分析

结构体socket用于描述一个socket,该结构体的定义如下:

  1. state定义了socket的状态(包括SS_UNCONNECTED、SS_CONNECTING、SS_CONNECTED、SS_DISCONNECTING等);
  2. file表示文件描述符,用于与vfs关联;
  3. struct sock *sk为socket结构体的关键成员变量,后面介绍;
  4. struct proto_ops *ops用于执行协议相关的socket处理接口。
struct socket {socket_state state;kmemcheck_bitfield_begin(type);short type;kmemcheck_bitfield_end(type);unsigned long flags;struct socket_wq __rcu *wq;struct file *file;struct sock *sk;const struct proto_ops *ops;};

2.struct sock分析

该结构体的定义如下(由于该结构体的内容较多,仅显示主要的几个成员变量),主要包括__sk_common变量包括源、目的ip地址等、socket收发的队列等信息

struct sock {struct sock_common __sk_common;#define sk_prot __sk_common.skc_protstruct sk_filter __rcu *sk_filter;struct socket_wq __rcu *sk_wq;struct proto *sk_prot_creator;struct sk_buff_head sk_receive_queue;struct sk_buff_head sk_write_queue;…}struct sock_common {/* 源、目的ip地址 */union {__addrpair skc_addrpair;struct {__be32 skc_daddr;__be32 skc_rcv_saddr;};};union {unsigned int skc_hash;__u16 skc_u16hashes[2];};/* 目的端口号等*/union {__portpair skc_portpair;struct {__be16 skc_dport;__u16 skc_num;};};unsigned short skc_family;//所属协议簇volatile unsigned char skc_state;//socket状态......struct proto *skc_prot;//传输层之上的协议处理接口#ifdef CONFIG_NET_NSstruct net *skc_net;#endif};

3.struct net_proto_family分析

该结构体主要用于说明网络协议簇,即针对ax25协议簇、inet4协议簇、inet6协议簇、ipx协议簇等

相关的定义,该结构体的定义如下:

  1. family用于说明协议簇的类型,目前linux支持的协议簇类型包括AF_UNIX、AF_LOCAL、AF_INET、AF_INET6、AF_NETLINK等;
  2. create接口函数,该接口用于初始化strcut sock类型的指针变量,根据传递的协议号,设置协议相关的接口函数。
struct net_proto_family {int family;int (*create)(struct net *net, struct socket *sock,int protocol, int kern);struct module *owner;};

在socketfs中定义了struct net_proto_family类型的全局指针数组net_families,该数组中包括了所有

linux内核支持的协议簇,在sockfs初始化时,调用接口sock_register将协议簇的指针存储至该数组中,该全局的变量的关联如下所示,在进行socket的创建时,会根据传递的协议簇类型,从该结构体中获取对应struct net_proto_family类型变量,并调用其create接口进行socket的初始化与操作接口的设置等操作。

该全局变量的作用:

  1. 表示所有在linux系统中已注册的协议簇变量;
  2. 在进行socket创建时,根据传递的协议簇类型,找到对应的协议簇变量,进入相应协议簇变量的处理分支,继续进行socket相关的处理操作。
51a43ca915eac48dcd0fc58529c6d411.png

4.struct inet_protosw分析(inet协议簇)

因本文主要介绍inet相关的实现,因此本处介绍struct inet_protosw结构体,

该结构体用于说明一个协议簇中针对不同协议所支持的协议处理操作以及对应的sock的表征,其主要内容如下:

  1. 其中type用于指示socket的类型,socket的类型包括SOCK_STREAM、SOCK_DGRAM具体的类型在下面有说明;
  2. protocol用于说明协议的类型(包括ip、tcp、udp、icmp、dccp等);
  3. prot用于指向协议相关的处理接口;
  4. proto_ops用于指向socket类型的处理接口,即SOCK_STREAM、SOCK_DGRAM等对应的处理接口
struct inet_protosw {struct list_head list;/* These two fields form the lookup key. */unsigned short type; /* This is the 2nd argument to socket(2). */unsigned short protocol; /* This is the L4 protocol number. */struct proto *prot;const struct proto_ops *ops;char no_check; /* checksum on rcv/xmit/none? */unsigned char flags; /* See INET_PROTOSW_* below. */};enum sock_type {SOCK_STREAM = 1,SOCK_DGRAM = 2,SOCK_RAW = 3,SOCK_RDM = 4,SOCK_SEQPACKET = 5,SOCK_DCCP = 6,SOCK_PACKET = 10,};

5.struct proto_ops分析(inet协议簇)

该结构体主要用于描述socket类型(SOCK_STREAM、SOCK_DGRAM等)的处理接口,该结构体定义如下:

family用于说明协议簇的类型

release、bind、connect、accept、poll、ioctl、listen、shutdown、setsockopt等接口,这些接口与sockfs提供的系统调用接口对应。

struct proto_ops {int family;struct module *owner;int (*release) (struct socket *sock);int (*bind)(struct socket *sock,struct sockaddr *myaddr, int sockaddr_len);int (*connect) (struct socket *sock,struct sockaddr *vaddr,int sockaddr_len, int flags);unsigned int (*poll) (struct file *file, struct socket *sock,struct poll_table_struct *wait);int (*ioctl) (struct socket *sock, unsigned int cmd,unsigned long arg);......};

6.struct proto 分析(inet协议簇)

该结构体主要用于具体协议相关的操作接口,对于大多数协议的socket而言,只需要使用上述5中注册的struct proto_ops提供的操作接口,即可完成对sockfs的系统调用的实现,而对一些协议(如udp、icmp、tcp协议),则需要特定的处理函数,这些处理函数的定义即使用struct proto结构体进行定义,该结构体的定义如下:

struct proto {void (*close)(struct sock *sk,long timeout);int (*connect)(struct sock *sk,struct sockaddr *uaddr,int addr_len);int (*disconnect)(struct sock *sk, int flags);struct sock * (*accept)(struct sock *sk, int flags, int *err);int (*ioctl)(struct sock *sk, int cmd, unsigned long arg);int (*init)(struct sock *sk);void (*destroy)(struct sock *sk);void (*shutdown)(struct sock *sk, int how);int (*setsockopt)(struct sock *sk, int level,int optname, char __user *optval,unsigned int optlen);int (*getsockopt)(struct sock *sk, int level,int optname, char __user *optval,int __user *option);…int *memory_pressure;long *sysctl_mem;int *sysctl_wmem;int *sysctl_rmem;int max_header;bool no_autobind;…struct list_head node;};

结构体之间的关联

上面已经介绍了sockfs相关的结构体,下面描述下这些结构体之间的关联。

struct inet_protosw、struct proto及struct proto_ops之间的关联

1de07ea51f34c2aa0d08cae92febb5af.png

在af_inet4中,这三个结构体之间的关联如上所示,另外针对strcut inet_protosw类型,定义了全局指针inetsw,用于链接inet4相关的所有strcut inet_protosw类型的变量,af_inet4注册的变量如下所示,包含了tcp、udp、icmp、raw socket等struct inet_protosw类型的变量。

b2b479459ff97a0b10a3947fbade2238.png

至此,完成了socketfs相关的结构体介绍,本小节主要讲述了各结构体的定义以及结构体的关联,通过将这些结构体之间的关系理清,能帮助我们更好的理解sockfs。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值