A socket is a method of communicating with a system process using the file descriptor of the systems.
1. The following is the structure that describes the socket address:
struct SOCKADDR {
sa_family_t sa_family; /* Address family, AF_XXX */
If the TCP/IP protocol is used, the Af_inet
Char sa_data[14]; /* bytes of protocol address */
};
2, the socket system calls:
We create sockets that are created with sockets.
System calls to the socket:
Each network operation function has a corresponding macro definition code
#define SYS_SOCKET 1/* Sys_socket (2) */
#define SYS_BIND 2/* Sys_bind (2) */
#define SYS_CONNECT 3/* Sys_connect (2) */
#define SYS_LISTEN 4/* Sys_listen (2) */
#define SYS_ACCEPT 5/* SYS_ACCEPT (2) */
#define SYS_GETSOCKNAME 6/* SYS_GETSOCKNAME (2) */
#define SYS_GETPEERNAME 7/* SYS_GETPEERNAME (2) */
#define SYS_SOCKETPAIR 8/* Sys_socketpair (2) */
#define SYS_SEND 9/* Sys_send (2) */
#define SYS_RECV/* SYS_RECV (2) */
#define SYS_SENDTO/* SYS_SENDTO (2) */
#define SYS_RECVFROM/* SYS_RECVFROM (2) */
#define SYS_SHUTDOWN/* Sys_shutdown (2) */
#define SYS_SETSOCKOPT/* SYS_SETSOCKOPT (2) */
#define SYS_GETSOCKOPT/* SYS_GETSOCKOPT (2) */
#define SYS_SENDMSG/* SYS_SENDMSG (2) */
#define SYS_RECVMSG */sys_recvmsg (2) */
In Linux, all network functions are implemented through Sys_socketcall:
Asmlinkage long Sys_socketcall (int call, unsigned long __user *args)
{
unsigned long a[6];
Unsigned long a0, A1;
int err;
Judgment of the scope of the incoming parameter
if (Call < 1 | | call > SYS_RECVMSG)
Return-einval;
/* Copy_from_user should be SMP safe. */
if (Copy_from_user (A, args, nargs[call))//Copy the user-state array to a
Return-efault;
Err = Audit_socketcall (Nargs[call]/sizeof (unsigned long), a);//record Audit data for Sys_socketcall
if (ERR)
return err;
a0 = a[0];
a1 = a[1];
Switch (call) {
Case Sys_socket:
Err = Sys_socket (a0, A1, A[2]);
Break
Case Sys_bind:
Err = Sys_bind (a0, (struct sockaddr __user *) a1, a[2]);
Break
Case Sys_connect:
Err = Sys_connect (a0, (struct sockaddr __user *) a1, a[2]);
Break
Case Sys_listen:
Err = Sys_listen (a0, A1);
Break
Case SYS_ACCEPT:
Err =
Sys_accept (a0, (struct sockaddr __user *) A1,
(int __user *) a[2]);
Break
Case Sys_getsockname:
Err =
Sys_getsockname (a0, (struct sockaddr __user *) A1,
(int __user *) a[2]);
Break
Case Sys_getpeername:
Err =
Sys_getpeername (a0, (struct sockaddr __user *) A1,
(int __user *) a[2]);
Break
Case Sys_socketpair:
Err = Sys_socketpair (a0, A1, A[2], (int __user *) a[3]);
Break
Case Sys_send:
Err = Sys_send (a0, (void __user *) a1, A[2], a[3]);
Break
Case SYS_SENDTO:
Err = Sys_sendto (a0, (void __user *) a1, A[2], a[3],
(struct sockaddr __user *) a[4], a[5]);
Break
Case SYS_RECV:
Err = Sys_recv (a0, (void __user *) a1, A[2], a[3]);
Break
Case Sys_recvfrom:
Err = Sys_recvfrom (a0, (void __user *) a1, A[2], a[3],
(struct sockaddr __user *) a[4],
(int __user *) a[5]);
Break
Case Sys_shutdown:
Err = Sys_shutdown (a0, A1);
Break
Case SYS_SETSOCKOPT:
Err = sys_setsockopt (a0, A1, A[2], (char __user *) a[3], a[4]);
Break
Case SYS_GETSOCKOPT:
Err =
Sys_getsockopt (A0, A1, A[2], (char __user *) a[3],
(int __user *) a[4]);
Break
Case SYS_SENDMSG:
Err = sys_sendmsg (a0, (struct MSGHDR __user *) a1, a[2]);
Break
Case SYS_RECVMSG:
Err = sys_recvmsg (a0, (struct MSGHDR __user *) a1, a[2]);
Break
Default
err =-einval;
Break
}
return err;
}
The Linux application Layer program implements network communication through the standard Bsdsocket interface. In BSD, the socket is used to describe a socket, mainly used in the BSD socket interface layer.
/**
* struct Socket-general BSD socket
* @state: Socket State (%ss_connected, etc)
* @flags: Socket flags (%SOCK_ASYNC_NOSPACE, etc)
* @ops: Protocol specific socket operations
* @fasync_list: Asynchronous Wake Up List
* @file: File back pointer for GC
* @sk: Internal networking protocol agnostic socket representation
* @wait: Wait queue for several uses
* @type: Socket type (%sock_stream, etc)
*/
struct Socket {
Socket_state State;
unsigned long flags;
const struct PROTO_OPS *ops;//socket function Operation table
struct Fasync_struct *fasync_list;
struct file *file;
struct sock *sk;
wait_queue_head_t wait;
Types of short type;//datagrams
};
struct sock *sk, pointing to the socket interface corresponding to the inet socket struct struct sock,
Create related sockets according to the Protocol
struct Net_proto_family {
int family;
Int (*create) (struct net *net, struct socket *sock, int protocol);//Creation function of the Protocol family
struct module *owner;
};
such as: IPV4
static struct net_proto_family Inet_family_ops = {
. Family = pf_inet,
. Create = Inet_create,
. Owner = This_module,
};
3. Creation of sockets:
Asmlinkage long Sys_socket (int family, int type, int protocol)
{
int retval;
struct socket *sock;
Creating sockets
retval = sock_create (family, type, protocol, &sock);
if (retval < 0)
Goto out;
retval = SOCK_MAP_FD (sock);//Associated File system
if (retval < 0)
Goto Out_release;
Out
/* It May is already another descriptor 8) not kernel problem. */
return retval;
Out_release:
Sock_release (sock);
return retval;
}
int sock_create (int family, int type, int protocol, struct socket **res)
{
Return __sock_create (Current->nsproxy->net_ns, family, type, protocol, res, 0);
}
The creation function of the socket
static int __sock_create (struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
{
int err;
struct socket *sock;
const struct net_proto_family *pf;
/*
* Check protocol is in range
*/
if (Family < 0 | | family >= nproto)
Return-eafnosupport;
if (Type < 0 | | type >= SOCK_MAX)
Return-einval;
/* compatibility.
This uglymoron was moved from INET layer to here to avoid
Deadlock in module load.
*/
if (family = = Pf_inet && type = = Sock_packet) {
static int warned;
if (!warned) {
warned = 1;
PRINTK (kern_info "%s uses obsolete (pf_inet,sock_packet) \ n",
CURRENT->COMM);
}
Family = Pf_packet;//af_inet
}
Tracing this function will find
Err = security_socket_create (family, type, protocol, Kern);
if (ERR)
return err;
/*
* Allocate the socket and allow the family to set things up. If
* The protocol is 0, the family are instructed to select a appropriate
* Default.
*/
Sock = Sock_alloc ();//Assigning the socket structure body space
if (!sock) {
if (Net_ratelimit ())
PRINTK (kern_warning "Socket:no more sockets\n");
Return-enfile; /* Not exactly a match, but its the
Closest POSIX thing */
}
Sock->type = type;
#if defined (CONFIG_KMOD)
/* Attempt to load a protocol module if the find failed.
*
* 12/09/1996 marcin:but! This makes really only sense, if the user
* Requested real, full-featured networking support upon configuration.
* Otherwise Module Support would break!
*/
if (net_families[family] = = NULL)
Request_module ("net-pf-%d", family);
#endif
Rcu_read_lock ();
PF = rcu_dereference (net_families[family]);
err =-eafnosupport;
if (!PF)
Goto Out_release;
/*
* We'll call the->create function, which possibly is in a loadable
* module, so we had to bump that loadable module refcnt first.
*/
if (!try_module_get (Pf->owner))
Goto Out_release;
/* now protected by module ref count */
Rcu_read_unlock ();
Err = pf->create (NET, sock, protocol);
if (Err < 0)
Goto Out_module_put;
/*
* Now to bump the refcnt of the [loadable] module, the owns this
* Socket at sock_release time we decrement it refcnt.
*/
if (!try_module_get (Sock->ops->owner))
Goto Out_module_busy;
/*
* Now that we ' re do with the->create function, the [loadable]
* Module can has its refcnt decremented
*/
Module_put (Pf->owner);
Err = security_socket_post_create (sock, family, type, protocol, Kern);
if (ERR)
Goto Out_sock_release;
*res = sock;
return 0;
Out_module_busy:
err =-eafnosupport;
Out_module_put:
Sock->ops = NULL;
Module_put (Pf->owner);
Out_sock_release:
Sock_release (sock);
return err;
Out_release:
Rcu_read_unlock ();
Goto Out_sock_release;
}
Analysis of the implementation of sockets in Linux-------creation