linux 创建本地socket 返回-1,Linux内核Socket实现之------Socket创建(1)

前言:

对于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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值