struct socket。
这是一个基本的BSD socket,我们调用socket系统调用创建的各种不同类型的socket,开始创建的都是它,到后面,各种不同类型的socket在它的基础上进行 各种扩展。struct socket是在虚拟文件系统上被创建出来的,可以把它看成一个文件,是可以被安全地扩展的。下面是其完整定义:
-
struct socket {
-
socket_state state;
-
unsigned long flags;
-
const struct proto_ops *ops;
-
struct fasync_struct *fasync_list;
-
struct file *file;
-
struct sock *sk;
-
wait_queue_head_t wait;
-
short type;
-
};
state用于表示socket所处的状态,是一个枚举变量,其类型定义如下:
-
typedef enum {
-
SS_FREE = 0,
-
SS_UNCONNECTED,
-
SS_CONNECTING,
-
SS_CONNECTED,
-
SS_DISCONNECTING
-
}socket_state;
该成员只对TCP socket有用,因为只有tcp是面向连接的协议,udp跟raw不需要维护socket状态。
flags是一组标志位,在内核中并没有发现被使用。
ops是协议相关的一组操作集,结构体struct proto_ops的定义如下:
-
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);
-
int (*socketpair)(struct socket *sock1, struct socket *sock2);
-
int (*accept)(struct socket *sock,struct socket *newsock, int flags);
-
int (*getname)(struct socket *sock, struct sockaddr *addr,int *sockaddr_len, int peer);
-
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);
-
int (*listen)(struct socket *sock, int len);
-
int (*shutdown)(struct socket *sock, int flags);
-
int (*setsockopt)(struct socket *sock, int level,
-
int optname, char __user *optval, int optlen);
-
int (*getsockopt)(struct socket *sock, int level,
-
int optname, char __user *optval, int __user *optlen);
-
int (*sendmsg)(struct kiocb *iocb, struct socket *sock,
-
struct msghdr *m, size_t total_len);
-
int (*recvmsg)(struct kiocb *iocb, struct socket *sock,
-
struct msghdr *m, size_t total_len, int flags);
-
int (*mmap)(struct file *file, struct socket *sock,struct vm_area_struct * vma);
-
ssize_t (*sendpage)(struct socket *sock, struct page *page,
-
int offset, size_t size, int flags);
-
};
-
协议栈中总共定义了三个strcut proto_ops类型的变量,分别是myinet_stream_ops, myinet_dgram_ops, myinet_sockraw_ops,对应流协议, 数据报和原始套接口协议的操作函数集。
type是socket的类型,对应的取值如下:
-
enum sock_type {
-
SOCK_DGRAM = 1,
-
SOCK_STREAM = 2,
-
SOCK_RAW = 3,
-
SOCK_RDM = 4,
-
SOCK_SEQPACKET = 5,
-
SOCK_DCCP = 6,
-
SOCK_PACKET = 10,
-
};
sk是网络层对于socket的表示,结构体struct sock比较庞大,这里不详细列出,只介绍一些重要的成员,
sk_prot和sk_prot_creator,这两个成员指向特定的协议处理函数集,其类型是结构体struct proto,该结构体也是跟struct proto_ops相似的一组协议操作函数集。这两者之间的概念似乎有些混淆,可以这么理解,struct proto_ops的成员操作struct socket层次上的数据,处理完了,再由它们调用成员sk->sk_prot的函数,操作struct sock层次上的数据。即它们之间存在着层次上的差异。struct proto类型的变量在协议栈中总共也有三个,分别是mytcp_prot,myudp_prot,myraw_prot,对应TCP, UDP和RAW协议。
sk_state表示socket当前的连接状态,是一个比struct socket的state更为精细的状态,其可能的取值如下:
-
enum {
-
TCP_ESTABLISHED = 1,
-
TCP_SYN_SENT,
-
TCP_SYN_RECV,
-
TCP_FIN_WAIT1,
-
TCP_FIN_WAIT2,
-
TCP_TIME_WAIT,
-
TCP_CLOSE,
-
TCP_CLOSE_WAIT,
-
TCP_LAST_ACK,
-
TCP_LISTEN,
-
TCP_CLOSING,
-
-
TCP_MAX_STATES
-
;
这些取值从名字上看,似乎只使用于TCP协议,但事实上,UDP和RAW也借用了其中一些值,在一个socket创建之初,其取值都是 TCP_CLOSE,一个UDP socket connect完成后,将这个值改为TCP_ESTABLISHED,最后,关闭sockt前置回TCP_CLOSE,RAW也一样。
sk_rcvbuf和sk_sndbuf分别表示接收和发送缓冲区的大小。sk_receive_queue和sk_write_queue分别为接收缓 冲队列和发送缓冲队列,队列里排列的是套接字缓冲区struct sk_buff,队列中的struct sk_buff的字节数总和不能超过缓冲区大小的设定。
接着上一篇,继续介绍struct sock。
sk_rmem_alloc, sk_wmem_alloc和sk_omem_alloc分别表示接收缓冲队列,发送缓冲队列及其它缓冲队列中已经分配的字节数,用于跟踪缓冲区的使用情况。
struct sock有一个struct sock_common成员,因为struct inet_timewait_sock也要用到它,所以把它单独归到一个结构体中,其定义如下:
-
struct sock_common {
-
unsigned short skc_family;
-
volatile unsigned char skc_state;
-
unsigned char skc_reuse;
-
int skc_bound_dev_if;
-
struct hlist_node skc_node;
-
struct hlist_node skc_bind_node;
-
atomic_t skc_refcnt;
-
unsigned int skc_hash;
-
struct proto *skc_prot;
-
};
struct inet_sock。
这是INET域专用的一个socket表示,它是在struct sock的基础上进行的扩展,在基本socket的属性已具备的基础上,struct inet_sock提供了INET域专有的一些属性,比如TTL,组播列表,IP地址,端口等,下面是其完整定义:
-
struct inet_sock {
-
struct sock sk;
-
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-
struct ipv6_pinfo *pinet6;
-
#endif
-
__u32 daddr;
-
__u32 rcv_saddr;
-
__u16 dport;
-
__u16 num;
-
__u32 saddr;
-
__s16 uc_ttl;
-
__u16 cmsg_flags;
-
struct ip_options *opt;
-
__u16 sport;
-
__u16 id;
-
__u8 tos;
-
__u8 mc_ttl;
-
__u8 pmtudisc;
-
__u8 recverr:1,
-
is_icsk:1,
-
freebind:1,
-
hdrincl:1,
-
mc_loop:1;
-
int mc_index;
-
__u32 mc_addr;
-
struct ip_mc_socklist *mc_list;
-
struct {
-
unsigned int flags;
-
unsigned int fragsize;
-
struct ip_options *opt;
-
struct rtable *rt;
-
int length;
-
u32 addr;
-
struct flowi fl;
-
} cork;
-
};
struct raw_sock
这是RAW协议专用的一个socket的表示,它是在struct inet_sock基础上的扩展,因为RAW协议要处理ICMP协议的过滤设置,其定义如下:
-
struct raw_sock {
-
struct inet_sock inet;
-
struct icmp_filter filter;
-
};
struct udp_sock
这是UDP协议专用的一个socket表示,它是在struct inet_sock基础上的扩展,其定义如下:
-
struct udp_sock {
-
struct inet_sock inet;
-
int pending;
-
unsigned int corkflag;
-
__u16 encap_type;
-
__u16 len;
-
};
struct inet_connection_sock
看完上面两个,我们觉得第三个应该就是struct tcp_sock了,但事实上,struct tcp_sock并不直接从struct inet_sock上扩展,而是从struct inet_connection_sock基础上进行扩展,struct inet_connection_sock是所有面向连接的socket的表示,关于该socket,及下面所有tcp相关的socket,我们在分析 tcp实现时再详细介绍,这里只列出它们的关系。
strcut tcp_sock
这是TCP协议专用的一个socket表示,它是在struct inet_connection_sock基础进行扩展,主要是增加了滑动窗口协议,避免拥塞算法等一些TCP专有属性。
struct inet_timewait_sock
struct tcp_timewait_sock
在struct inet_timewait_sock的基础上进行扩展。
struct inet_request_sock
struct tcp_request_sock
在struct inet_request_sock的基础上进行扩展。