socket系统调用过程

本文详细介绍了socket系统调用的过程,从sys_socket()开始,经过sock_create()和__sock_create(),到sock_alloc()、alloc_inode()、inet_create()等,逐步解析如何创建和初始化网络层socket。重点讨论了sock_alloc_inode()和inet_create()在socket分配和网络层结构建立中的作用。最后,概述了sk_alloc()和sock_init_data()如何完成socket与sk结构的关联。
摘要由CSDN通过智能技术生成

 

一. socket()函数系统调用过程

在sys_socketcall()函数中可以看到,socket系统调用最终调用的是sys_socket()函数

sys_socket()函数声明如下:

asmlinkage long sys_socket(int, int, int);

同样地,sys_socket()函数实现为:

1. sys_socket()

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及inode*/
	retval = sock_create(family, type, protocol, &sock);
	if (retval < 0)
		goto out;
	
	/*创建file,完成fd与file绑定,file与socket绑定*/
	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;
}

参数kern:表示由应用程序还是内核创建该套接口,一般为0(表示应用程序),或者1(表示内核)。

2. sock_create()函数:

这个函数是对__socket_create函数的封装,直接调用__sock_create()函数。

int sock_create(int family, int type, int protocol, struct socket **res)
{
	return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
}

3. __sock_create()函数

创建socket及inode

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
	 */
	/*family和type字段范围检查*/
	if (family < 0 || family >= NPROTO)
		return -EAFNOSUPPORT;
	if (type < 0 || type >= SOCK_MAX)
		return -EINVAL;

	/* Compatibility.

	   This uglymoron is moved from INET layer to here to avoid
	   deadlock in module load.
	 */
	/*兼容性考虑,IPv4协议族的SOCK_PACKET已经废弃,当family ==F_INET && type == SOCK_PACKET时,
	强制把family改为PF_PACKET。*/
	if (family == PF_INET && type == SOCK_PACKET) {
		static int warned;
		if (!warned) {
			warned = 1;
			pr_info("%s uses obsolete (PF_INET,SOCK_PACKET)\n",
				current->comm);
		}
		family = PF_PACKET;
	}
	
	/*安全模块对套接口的创建做检查,安全模块不是网络中必需的组成部门,不做讨论。*/
	// 检查权限,并考虑协议集、类型、协议,以及 socket 是在内核中创建还是在用户空间中创建
    // 可以参考:https://www.ibm.com/developerworks/cn/linux/l-selinux/
	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_inode_cache缓存中分配与套接口关联的i结点和套接口,同时
	初始化i结点和套接口,失败则直接返回错误码。*/
	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;

/*如果协议族支持内核模块动态加载,但在创建此协议族类型的套接字时,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值