前言:
对于Linux内核的Socket系列文章都是依据于:Linux-3.14.5的版本内核分析,对于文中的注释和问题的说明也参考了网络上经典分析文章,对他们奉献表示感谢!
转载请标明:http://blog.chinaunix.net/uid-20788636-id-4408261.html
1. Socket内核调用数SYSCALL_DEFINE3
Socket的创建是在用户空间调用socket系统函数完成的,创建一个Socket返回一个文件描述符fd,内核的系统调用接口为SYSCALL_DEFINE3(socket,
int, family, int, type, int, protocol),在net/socket.c文件中,下面我们看一下内核中的源码实现。
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;
//调用创建socket的函数
retval
= sock_create(family, type, protocol, &sock);//------参考下面的分析
if
(retval < 0)
goto
out;
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;
}
1.1 socket_create函数
对于sock_create(family,
type, protocol, &sock)函数调用的是包囊函数,
__sock_create(current->nsproxy->net_ns,
family, type, protocol, res, 0);
对于__sock_create函数的定义如下:
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检查协议的范围,现在内核定义的最大范围为41,这里的family指的是AF_INET6,AF_INET协议簇
#define NPROTO AF_MAX
#define AF_MAX 41 /* For now.. */
*/
if
(family < 0 || family >= NPROTO)
return
-EAFNOSUPPORT;
if
(type < 0 || type >= SOCK_MAX)//这里的type是socket的类型例如SOCK_STREAM
return
-EINVAL;
/*
Compatibility.
This uglymoron is moved from INET layer to
here to avoid
deadlock in module load.
*/
if
(family == PF_INET && type == SOCK_PACKET) {//如果是该类型的socket,对family进行重新的赋值
static
int warned;//这里自动初始化为0,
if
(!warned) {
warned
= 1;
printk(KERN_INFO
"%s uses obsolete (PF_INET,SOCK_PACKET)\n",
current->comm);
}
family
= PF_PACKET;//赋值为PF_PACKET
}
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 is instructed to select an appropriate
* default.这里调用sock_alloc分配sock,见下面的分析
*/
sock = sock_alloc();
if
(!sock) {
net_warn_ratelimited("socket:
no more sockets\n");
return
-ENFILE; /* Not exactly a match,
but its the
closest posix thing */
}
sock->type
= type;
#ifdef CONFIG_MODULES
/*
Attempt to load a protocol module if the find failed.
*
* 12/09/1996 Marcin: But! this makes REALLY
only sense, if the user