2.1 Socket系统调用

  TCP是传输层协议,网络层使用IPv4或IPv6协议,即TCP报文作为IPv4或IPv6报文的数据部分。本文中将使用IPv4协议的TCP称为TCPv4,将使用IPv6的TCP称为TCPv6。使用不同的IP协议对于TCP的影响主要是连接查找、检验和计算等与IP地址相关的部分,核心功能并无差异。故此在以下的代码分析过程中会以TCPv4为主。

  先来看看socket系统调用的函数原型:

int socket(int domain, int type, int protocol);

  参数解析:

  domain参数用来指定通信协议族,对于TCP而言其值应为AF_INET(IPv4协议)或AF_INET6(IPv6协议);

  type参数用来指定通信语义,此参数应选择SOCK_STREAM,其含义是“Provides sequenced, reliable, two-way, connection-based byte streams.   An  out-of-band data transmission mechanism may be supported”,TCP的特性正好符合此语义;

  protocol参数指定socket所使用的协议,此参数取值IPPROTO_IP(值为0)或IPPROTO_TCP(值为6)代表TCP协议。取值为0也能代表TCP协议,是因为protocol为0时代表取给定domain的type中的默认协议,而TCP是AF_INET|AF_INET6中SOCK_STREAM类型的默认协议。

  socket系统调用成功的话返回一个文件描述符,其它API就通过这个描述符操控socket。

  问题来了:socket系统调用究竟对内核做了什么?socket对于TCP究竟有何意义?下面我们一起通过分析Linux内核代码来找到这些问题的答案。

  Socket系统调用对应的内核函数为:

1360 SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
1361 {
1362     int retval;
1363     struct socket *sock;
1364     int flags;
1365 
...
1380     retval = sock_create(family, type, protocol, &sock);
1381     if (retval < 0)
1382         goto out;
1383 
1384     retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
1385     if (retval < 0)
1386         goto out_release;
1387 
1388 out:
1389     /* It may be already another descriptor 8) Not kernel problem. */
1390     return retval;
...
1395 }
  只要弄明白sock_create函数和sock_map_fd函数做了什么,自然就能明白socket系统调用的功能。先来看sock_create函数:

1235 int __sock_create(struct net *net, int family, int type, int protocol,
1236              struct socket **res, int kern)
1237 {
1238     int err;
1239     struct socket *sock;
...
1269     /*
1270      *  Allocate the socket and allow the family to set things up. if
1271      *  the protocol is 0, the family is instructed to select an appropriate
1272      *  default.
1273      */
1274     sock = sock_alloc();
1275     if (!sock) {
1276         net_warn_ratelimited("socket: no more sockets\n");
1277         return -ENFILE; /* Not exactly a match, but its the
1278                    closest posix thing */
1279     }
1280 
1281     sock->type = type;
...
1295     pf = rcu_dereference(net_families[family]);
...
1310     err = pf->create(net, sock, protocol, kern);
...
1329     *res = sock;
1330 
1331     return 0;
...
  sock_create函数申请了一个struct socket结构体sock,又调用pf->create指向的函数对通过sock进行初始化。分析inet_init等网络子系统初始化函数得知,pf->
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值