[net/socket.c]
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
int retval;
struct socket *sock;
int flags;
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
* 同时分配了一个inode
*/
retval = __sock_create(current->nsproxy->net_ns, family, type, protocol, &sock, 0);
SOCK_TYPE_MASK值为0xf;SOCK_CLOEXEC表示当fork子进程后,在子进程中调用exec时会自动把从父进程继承过来的socket句柄关闭;SOCK_NONBLOCK表示创建的文件句柄是非阻塞的。flags的值是取type的高位,只充许设置刚提到的两个值。然后将type设置为它的低4位。当flags设置了SOCK_NONBLOCK,将其调整为O_NONBLOCK。
然后就是分配socket,第一个参数为当前进程的网络名字空间:
[socket->__sock_create]
int __sock_create(struct net *net, int family, int type, int protocol, struct socket **res, int kern)
{
struct socket *sock;
sock = sock_alloc();
先对family和type的范围进行了检查,然后就分配socket:
[socket->__sock_create->sock_alloc]
static struct socket *sock_alloc(void)
{
struct inode *inode;
/* 从sockfs创建一个inode
* 实际的分配工作由sock_alloc_inode(通过sockfs_ops->alloc_inode调用)完成
*/
inode = new_inode_pseudo(sock_mnt->mnt_sb);
[socket->__sock_create->sock_alloc->new_inode_pseudo]
struct inode *new_inode_pseudo(struct super_block *sb)
{
struct inode *inode = alloc_inode(sb);
if (inode) {
spin_lock(&inode->i_lock);
inode->i_state = 0;
spin_unlock(&inode->i_lock);
INIT_LIST_HEAD(&inode->i_sb_list);
}
return inode;
}
aloc_inode分配了一个inode-socket对,返回当中的inode
[socket->__sock_create->sock_alloc]
/* 通过inode得到socket
* 上面通过sock_alloc_inode得到的是一个socket_alloc结构
*/
sock = SOCKET_I(inode);
kmemcheck_annotate_bitfield(sock, type);
inode->i_ino = get_next_ino();
inode->i_mode = S_IFSOCK | S_IRWXUGO;
inode->i_uid = current_fsuid(); // UID for VFS ops
inode->i_gid = current_fsgid(); // GID for VFS ops
inode->i_op = &sockfs_inode_ops;
/*sockets_in_use为全局变量,现在socket的数量加1
*/
this_cpu_add(sockets_in_use, 1);
return sock;
}
设置inode的节点号;是一个socket文件,所有人可读写,可执行;设置用户ID,组ID;设置对inode的操作为sockfs_inode_ops。
[socket->__sock_create]
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
* requested real, full-featured networking support upon configuration.
* Otherwise module support will break!
*/
if (rcu_access_pointer(net_families[family]) == NULL)
request_module("net-pf-%d", family);
#endif
设置sock的类型,如果net_families数组中下标为family的值为空,加载相应的模块。
static const struct net_proto_family __rcu *net_families[NPROTO] __read_mostly;
是一个数组,大小为41,每种支持socket的family都注册自己的net_proto_family结构指针到此数组中。后面以IP为例,它的family为PF_INET:
static const struct net_proto_family inet_family_ops = {
.fam