TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现
题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术
轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com
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的实现的更多相关文章
- 源码分析:动态分析 Linux 内核函数调用关系
源码分析:动态分析 Linux 内核函数调用关系 时间 2015-04-22 23:56:07 泰晓科技 原文 http://www.tinylab.org/source-code-analysi ...
- 【Linux 内核网络协议栈源码剖析】网络栈主要结构介绍(socket、sock、sk_buff,etc)
原文:http://blog.csdn.net/wenqian1991/article/details/46700177 通过前面的分析,可以发现,网络协议栈中的数据处理,都是基于各类结构体,所有有关 ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- jquery2源码分析系列
学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- spring源码分析系列
spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor.BeanDefinitionRegistryPostProcessor spring源码分析系列 ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
- swoft| 源码解读系列一: 好难! swoft demo 都跑不起来怎么破? docker 了解一下呗~
title: swoft| 源码解读系列一: 好难! swoft demo 都跑不起来怎么破? docker 了解一下呗~description: 阅读 sowft 框架源码, swoft 第一步, ...
随机推荐
- 【水】HDU 2099——整除的尾数
来源:点击打开链接 数据范围小,枚举水过就行了……不过要注意格式! #include <iostream> #include <cstring> #include <io ...
- 使用OVS
创建节点: 需要在组件上引用OVS组件WDR_OVS:引用后需要更改添加节点属性值如下: 布局如下: 在view中也添加ovs组件 新建事件方法: ON_EVENT 代码如下: METHOD on_e ...
- 关于如何解决谷歌Chrome浏览器空白页的问题
谷歌Chrome浏览器突然不打开任何网页,无论是任何站点(如http://www.baidu.com), 还是Chrome浏览器的设置页面(chrome://settings/), 扩展页面 ( ch ...
- poj2418 map 快排水过
/*计算每个单词的百分比按字典序输出*/ #include <cstdio>#include<cstdlib>#include <cstring>#include ...
- 使用Intent 将底层栈里所有的activity都清理掉
可以利用清理历史栈的方法,来巧妙关闭所有activity,首先用一个设置为不可见的activity A来启动程序,这个activity A的作用只是用来垫栈底,只有启动和退出程序才会用到这个activ ...
- Java使用HttpURLConnection上传文件
从普通Web页面上传文件非常easy.仅仅须要在form标签叫上enctype="multipart/form-data"就可以,剩余工作便都交给浏览器去完毕数据收集并发送Http ...
- MFC-消息分派
前言 由于工作需要,这几天学了一点MFC,在AFX里看到很多熟悉的东西,如类型信息,序列化,窗口封装和消息分派.几乎每个界面库都必须提供这些基础服务,但提供的手法却千差万别.MFC大量地借用了宏,映射 ...
- Exception in thread "main" java.net.BindException: Address already in use: JVM_Bind
Exception in thread "main" java.net.BindException: Address already in use: JVM_Bind at ...
- linux 查看网络负载
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' 前面的 netstat -n是netstat的命令,windo ...
- javascript(五)验证
<input id="domo" type="text"> <script> function my_function(){ var ...