- socket 结构
/** * struct socket - general BSD socket * @state: socket state (%SS_CONNECTED, etc) * @type: socket type (%SOCK_STREAM, etc) * @flags: socket flags (%SOCK_NOSPACE, etc) * @ops: protocol specific socket operations * @file: File back pointer for gc * @sk: internal networking protocol agnostic socket representation * @wq: wait queue for several uses */ typedef enum { SS_FREE = 0, /* not allocated */ SS_UNCONNECTED, /* unconnected to any socket */ SS_CONNECTING, /* in process of connecting */ SS_CONNECTED, /* connected to socket */ SS_DISCONNECTING /* in process of disconnecting */ } socket_state; /* Historically, SOCKWQ_ASYNC_NOSPACE & SOCKWQ_ASYNC_WAITDATA were located * in sock->flags, but moved into sk->sk_wq->flags to be RCU protected. * Eventually all flags will be in sk->sk_wq_flags. */ #define SOCKWQ_ASYNC_NOSPACE 0 #define SOCKWQ_ASYNC_WAITDATA 1 #define SOCK_NOSPACE 2 #define SOCK_PASSCRED 3 #define SOCK_PASSSEC 4
struct socket_wq { /* Note: wait MUST be first field of socket_wq */ wait_queue_head_t wait; struct fasync_struct *fasync_list; unsigned long flags; /* %SOCKWQ_ASYNC_NOSPACE, etc */ struct rcu_head rcu; } ____cacheline_aligned_in_smp;
struct socket { socket_state state;//套接口所处的状态对tcp 套接口有意义 SS_CONNECTED kmemcheck_bitfield_begin(type); short type; kmemcheck_bitfield_end(type); unsigned long flags; struct socket_wq __rcu *wq;// 包含了等待该套接字的进程队列 以及异步通知队列 struct file *file; //指向了和套接字相关联的file 结构 struct sock *sk;//和套接字相关联的传输控制块 const struct proto_ops *ops; //对于tcp udp raw 分别对应 inet_stream_ops inet_dgram_ops inet_sockraw_ops };
proto_ops 结构完成了从协议无关的socket 到协议层的传输层转接,结构proto 将传输层映射到网络层,
所以可知:每一个传输层都需要顶一个特定的proto_ops和proto实例,参考static struct inet_protosw inetsw_array[] 数组;
在网络子系统初始化的时候,根据其type 注册到一个list_head的结构数组inetsw[ ] 中, socket中类型相同的inet_protosw结构在inetsw[ ] 中以其对应的元素组层一个双向链表;
Socket系统调用如下:
/** family:创建socket的协议族 PF_INET PF_UNIX type: 创建socket的类型 SOCK_STREAM. SOCK_DGRAM.SOCK_RAW protocol: 传输层协议:IPPROTO_TCP IPPROTO_UDP **/ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) { int retval; struct socket *sock; int flags; /* Check the SOCK_* constants for consistency. */ BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC); BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); flags = type & ~SOCK_TYPE_MASK; if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) return -EINVAL; type &= SOCK_TYPE_MASK; if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; retval = sock_create(family, type, protocol, &sock);//创建一个socket if (retval < 0) goto out; //给创建的socket 分配一个file fd 并绑定 retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); if (retval < 0) goto out_release; out: /* It may be already another descriptor 8) Not kernel problem. */ return retval; out_release: sock_release(sock); return retval;