Socket 套接字的系统调用

时间:2021-01-07 11:04:28
  • 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 套接字的系统调用

 

Socket 套接字的系统调用

 

 

Socket 套接字的系统调用

 


 Socket系统调用如下:

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;