- 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;