TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现

时间:2022-08-24 09:54:50

题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术


轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.comTCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现


linux内核协议栈中对于socket相关API的实现


首先对于内核中断向量表不是很熟悉的请先参考一下博文:《TCP/IP协议栈源码图解分析系列6:linux 系统调用中断向量表》 URL:http://blog.csdn.net/byhankswang/article/details/9284023

首先应该做的事情

定义好了内核中断向量表之后,需要做的就是当用户层程序陷入到内核态之后,通过内核中断向量表找到了内核中对于该系统调用的实现。补充一下内核中SYSCALL_DEFINE的用法:

SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol){ ….}

<=>SYSCALL_DEFINEX(3,_socket,__VA_ARGS__)

<=>_SYSCALL_DEFINE(3,_socket,__VA_ARGS__)

<=>asmlinkage long sys_socket(int family,int type,int protocol)

SYSCALL_DEFINE* 把内核中断向量表和内核实现完美的衔接了起来。

用户层API内核是如何实现的

以socket相关的套接字编程接口为例(linux 3.9.3):

socket.c:1382:SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
socket.c:1423:SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
socket.c:1519:SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
socket.c:1548:SYSCALL_DEFINE2(listen, int, fd, int, backlog)
socket.c:1581:SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
socket.c:1662:SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
socket.c:1680:SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
socket.c:1712:SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
socket.c:1743:SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
socket.c:1775:SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
socket.c:1822:SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
socket.c:1834:SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
socket.c:1890:SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
socket.c:1924:SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
socket.c:1954:SYSCALL_DEFINE2(shutdown, int, fd, int, how)
socket.c:2096:SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
socket.c:2171:SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
socket.c:2269:SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
socket.c:2393:SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
socket.c:2435:SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)

然后我们看相关的源代码以socket和bind为例:

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;

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;
}

SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
{
struct socket *sock;
struct sockaddr_storage address;
int err, fput_needed;

sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
err = move_addr_to_kernel(umyaddr, addrlen, &address);
if (err >= 0) {
err = security_socket_bind(sock,
  (struct sockaddr *)&address,
  addrlen);
if (!err)
err = sock->ops->bind(sock,
     (struct sockaddr *)
     &address, addrlen);
}
fput_light(sock->file, fput_needed);
}
return err;
}

我们可以看到,只要抓住了主要的脉络,分析内核协议栈是很简单的事情,用侯捷先生的话说“源码在手,了无秘密”。

TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现的更多相关文章

  1. 源码分析:动态分析 Linux 内核函数调用关系

    源码分析:动态分析 Linux 内核函数调用关系 时间 2015-04-22 23:56:07  泰晓科技 原文  http://www.tinylab.org/source-code-analysi ...

  2. 【Linux 内核网络协议栈源码剖析】网络栈主要结构介绍(socket、sock、sk&lowbar;buff,etc)

    原文:http://blog.csdn.net/wenqian1991/article/details/46700177 通过前面的分析,可以发现,网络协议栈中的数据处理,都是基于各类结构体,所有有关 ...

  3. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  4. jquery2源码分析系列

    学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...

  5. &lbrack;转&rsqb;jQuery源码分析系列

    文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...

  6. spring源码分析系列

    spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor.BeanDefinitionRegistryPostProcessor spring源码分析系列 ...

  7. jQuery源码分析系列&lpar;转载来源Aaron&period;&rpar;

    声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...

  8. jQuery源码分析系列——来自Aaron

    jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...

  9. swoft&vert; 源码解读系列一&colon; 好难&excl; swoft demo 都跑不起来怎么破&quest; docker 了解一下呗~

    title: swoft| 源码解读系列一: 好难! swoft demo 都跑不起来怎么破? docker 了解一下呗~description: 阅读 sowft 框架源码, swoft 第一步, ...

随机推荐

  1. 使用EntityFramework6连接MySql数据库(db first方式)

    准备工具: VS2013.MySQL For VisualStudio 1.1.4.Connector/Net 6.8.3(百度网盘里) 程序包管理器执行命令: Install-Package Ent ...

  2. 学习Linux系列--安装Ubuntu

    最近学习Linux,使用虚拟机太不方便,于是购买了阿里云最便宜的云主机作为学习设备. 本系列文章记录了个人学习过程的点点滴滴. 学习Linux系列--安装Ubuntu 学习Linux系列--安装软件环 ...

  3. Mybatis 开启事务&commat;Transactional

  4. NSJSONSerialization-JSON数据与NSDictionary和NSArray之间的转化

    转载▼     在iOS  5 中,苹果引入了一个解析JSON串的NSJSONSerialization类. 通过该类,我们可以完成JSON数据与NSDictionary和NSArray之间的转化. ...

  5. javascript回调函数

    function $$(f) { if (typeof f == 'function') {//f是一个函数 f(); } else { alert('not a function'); } } $$ ...

  6. Hibernate学习笔记①

    ---恢复内容开始--- 1.JavaEE的三层结构 WEB层--Service层--DAO层 2.Hibernate版本 Hibernate3.x  4.x  5.x 4版本是过渡版本 不使用  5 ...

  7. spring源码分析之spring-jdbc模块详解

    0 概述 Spring将替我们完成所有使用JDBC API进行开发的单调乏味的.底层细节处理工作.下表描述了哪些是spring帮助我们做好的,哪些是我们要做的. Action  Spring  You ...

  8. C&num; SharpMap的简单使用

    本文是利用ShapMap实现GIS的简单应用的小例子,以供学习分享使用.关于SharpMap的说明,网上大多是以ShapeFile为例进行简单的说明,就连官网上的例子也不多.本文是自己参考了源代码进行 ...

  9. 在有 UI 线程参与的同步锁(如 AutoResetEvent)内部使用 await 可能导致死锁

    AutoResetEvent.ManualResetEvent.Monitor.lock 等等这些用来做同步的类,如果在异步上下文(await)中使用,需要非常谨慎. 本文将说一个在同步上下文中非常常 ...

  10. js下载文件

    本文的前提是:后台给的是一个可以下载的url的情况下的下载: 怎样的文件url才能触发浏览器的下载行为?(转自SF) 能触发浏览器下载的url有两类: response header中指定了Conte ...