linux网络子系统内核分析
1.选择路由
若要将数据包发至PC2,则linux系统通过查询路由表可知168.1.1.10(目的地址)的网关地址为192.168.1.1,此时linux系统选择网卡1发送数据包。
2.邻居子系统(通过arp协议建立起邻居的信息)
选择网卡1发送数据时,首先将数据包发给邻居(网关),再由邻居转发至后面,若要发送给邻居,则必须知道邻居的MAC地址,若不知道邻居的MAC地址,则需要通过arp请求包获取邻居的MAC地址。
Linux网络体系结构由以下五个部分组成 1)系统调用接口 2)协议无关接口 3)网络协议 4)设备无关接口 5 设备驱动程序。下面分别简述五个部分:
1)系统调用接口
系统调用接口是用户空间的应用程序正常访问内核的唯一合法途径(终端和陷入也可访问内核)。如:
asmlingkage long sys_getpid(void)
{
return current->pid;
}
系统调用一般由sys开头 ,前面的修饰符是asmlingkage,表示函数由堆栈获得参数。
2)协议无关接口
协议无关接口是由socket来实现的。它提供了一组通用函数来支持各种不同协议。
通过网络栈进行的通信都需要对 socket 进行操作。Linux 中的 socket 结构是 struct sock ,这个结构是在 linux/include/net/sock.h 中定义的。这个巨大的结构中包含了特定 socket 所需要的所有状态信息,其中包括 socket 所使用的特定协议和在 socket 上可以执行的一些操作。
网络子系统可以通过一个定义了自己功能的特殊结构来了解可用协议。每个协议都维护了一个名为 proto 的结构(可以在 linux/include/net/sock.h 中找到)。这个结构定义了可以在从 socket 层到传输层中执行特定的 socket 操作
3)网络协议
Linux支持多种网络协议,可以在<linux/socket.h>中查到所支持的网络协议:
#define AF_UNIX 1 /* Unix domain sockets */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* Internet IP Protocol */
#define AF_AX25 3 /* Amateur Radio AX.25 */
#define AF_IPX 4 /* Novell IPX
… …
其中每一个所支持的协议对应net_family[]数组中的一项,net_family[]是结构体指针数组,其中的每一项都是一个结构体指针,指向一个net_proto_family 结构
struct net_proto_family {
int family;
int (*create) (struct socket * sock, int protocol);
short authentication;
short encryption;
short encrypt_net;
struct module *owner;
};这个结构体中注册了关于协议的信息。
4)设备无关接口
设备无关接口是由net_device实现的。任何设备和上层通信都是通过net_device设备无关接口。
它将协议与具有很多各种不同功能的硬件设备连接在一起。这一层提供了一组通用函数供底层网络设备驱动程序使用,让它们可以对高层协议栈进行操作。
首先,设备驱动程序可能会通过调用 register_netdevice 或 unregister_netdevice 在内核中进行注册或注销。调用者首先填写 net_device 结构,然后传递这个结构进行注册。内核调用它的 init 函数(如果定义了这种函数),然后执行一组健全性检查,并创建一个 sysfs 条目,然后将新设备添加到设备列表中(内核中的活动设备链表)。在 linux/include/linux/netdevice.h 中可以找到这个 net_device 结构。这些函数都是在 linux/net/core/dev.c 中实现的。
要从协议层向设备中发送 sk_buff ,就需要使用 dev_queue_xmit 函数。这个函数可以对 sk_buff 进行排队,从而由底层设备驱动程序进行最终传输(使用 sk_buff 中引用的 net_device 或 sk_buff->dev 所定义的网络设备)。dev 结构中包含了一个名为 hard_start_xmit 的方法,其中保存有发起 sk_buff 传输所使用的驱动程序函数。
报文的接收通常是使用 netif_rx 执行的。当底层设备驱动程序接收一个报文(包含在所分配的 sk_buff 中)时,就会通过调用 netif_rx 将 sk_buff 上传至网络层。然后,这个函数通过 netif_rx_schedule 将 sk_buff 在上层协议队列中进行排队,供以后进行处理。可以在 linux/net/core/dev.c 中找到 dev_queue_xmit 和 netif_rx 函数。
5)设备驱动程序
网络栈底部是负责管理物理网络设备的设备驱动程序。例如,包串口使用的 SLIP 驱动程序以及以太网设备使用的以太网驱动程序都是这一层的设备。
在进行初始化时,设备驱动程序会分配一个 net_device 结构,然后使用必须的程序对其进行初始化。这些程序中有一个是 dev->hard_start_xmit ,它定义了上层应该如何对 sk_buff 排队进行传输。这个程序的参数为 sk_buff 。这个函数的操作取决于底层硬件,但是通常 sk_buff 所描述的报文都会被移动到硬件环或队列中。就像是设备无关层中所描述的一样,对于 NAPI 兼容的网络驱动程序来说,帧的接收使用了 netif_rx 和 netif_receive_skb 接口。NAPI 驱动程序会对底层硬件的能力进行一些限制。
分析内核代码实现:
1.发送UDP数据包
在应用程序中
通过socket()函数建立一个socket,然后通过write()函数讲数据写入socket发送出去
在内核中:
a.在系统调用层和协议无关层中
首先通过socket_file_ops结构找出应用程序在内核中的入口,其函数为sock_aio_write,紧接着调用do_sock_write---__sock_sendmsg---__sock_sendmsg_nosec
b.在网络协议层中
调用udp_sendmsg---ip_route_output_flow(选择路由) udp_flush_pending_frames---ip_flush_pending_frames(ip协议入口)---ip_local_out---dst_output---ip_finish_output---ip_finish_output2---arp_generic_ops->neigh_resolve_output(建立邻居信息)
c.在设备无关接口中
调用dev_queue_ximt---dev_hard_start_xmit
d.在驱动程序层中
调用ndo_start_xmit
2.接收IP数据包
在应用程序中
通过系统调用recvmsg函数获取包的内容
在内核中:
网卡接收到数据包之后发生中断,通过netif_rx(此处触发一个软中断,当处理器空闲时再处理)函数将包递给上层的netif_rx_action(除驱动层之外,上面四层的总入口),继续调用netif_receive_skb(判断由哪个协议处理该包)---deliver_skb,然后将数据包递交给ip协议层处理(ip_rcv-ip协议栈层处理入口),紧接着有丢给udp协议层处理(udp_rcv-udp协议栈层处理入口),udp层处理完之后,递交给sock->ops->recvmsg,即为recvmsg系统调用对应的函数。
linux网络子系统内核分析的更多相关文章
- Linux网络子系统
再Linux的世界里,万物皆文件,通过虚拟文件系统VFS,程序可以用标准的Linux系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作.下面我们揭示Linux网络子系统的秘密 sockfs ...
- Linux 网络子系统
今天记录一下Linux网络子系统相关的东西. 因为感觉对这一块还是有一个很大的空白,这件事情太可怕了. 摘抄多份博客进行总结一下Linux网络子系统的相关东西. 一. Linux网络子系统体系结构 L ...
- Linux 网络子系统之网络协议接口层(一)
Linux 网络设备驱动之网络协议接口层介绍. 网络协议接口层最主要的功能是给上层协议提供透明的数据包发送和接收接口. 当上层ARP或IP需要发送数据包时,它将调用网络协议接口层的dev_queue_ ...
- Linux网络编程&内核学习
c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...
- Linux输入子系统框架分析(1)
在Linux下的输入设备键盘.触摸屏.鼠标等都能够用输入子系统来实现驱动.输入子系统分为三层,核心层和设备驱动层.事件层.核心层和事件层由Linux输入子系统本身实现,设备驱动层由我们实现.我们在设备 ...
- Linux网络编程案例分析
本代码来自于博主:辉夜星辰 本篇主要对运行代码中出现的问题进行分析,代码本身的内容后续展开讨论. 服务器端代码 /* Linux网络编程之TCP编程,服务器端读数据 socket函数之后,返回值ser ...
- Linux input子系统实例分析(一)
这是一个简单的输入设备驱动实例.这个输入设备只有一个按键,按键被连接到一条中断线上,当按键被按下时,将产生一个中断,内核将检测到这个中断,并对其进行处理.该实例的代码如下: 1: #inclu ...
- Linux网络子系统之---- PHY 配置
MII即媒体独立接口,也叫介质无关接口. 它包括一个数据接口,以及一个MAC和PHY之间的管理接口(图1). 数据接口包括分别用于发送器和接收器的两条独立信道.每条信道都有自己的数据.时钟和控制信号. ...
- Linux input子系统实例分析(二)
紧接着上一节的实例我们来分析调用的input子系统的接口: 1. input_dev,用来标识输入设备 1: struct input_dev { 2: const char *name; //设备名 ...
随机推荐
- blocksit
<!DOCTYPE html> <html> <head> <title>Sc.Chinaz.Com</title> & ...
- pytest学习笔记(三)
接着上一篇的内容,这里主要讲下参数化,pytest很好的支持了测试函数中变量的参数化 一.pytest的参数化 1.通过命令行来实现参数化 文档中给了一个简单的例子, test_compute.py ...
- 初探接口测试框架--python系列3
点击标题下「微信」可快速关注 坚持的是分享,搬运的是知识,图的是大家的进步,没有收费的培训,没有虚度的吹水,喜欢就关注.转发(免费帮助更多伙伴)等来交流,想了解的知识请留言,给你带来更多价值,是我们期 ...
- Jackson 框架,轻易转换JSON(转)
Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json.xml转换成Java对象. 相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也 ...
- 【翻译习作】 Windows Workflow Foundation程序开发-第一章02
1.2 Windows Workflow概览 微软的Windows Workflow Foundation(简称WF)是.NET框架3.0版的一部分..NET3.0其它主要部分是Window ...
- 2014年值得学习的25个PS CS6教程(一)
热爱PS的朋友看过来~~~下面跟大家推荐10个高端大气上档次的PS教程(都是英文的哦) 1.为4D电影创建一副3D海报 2.制作3D水果文字 3.肖像图混合数字工艺 4.‘Doctrich – Pos ...
- 慕课网-安卓工程师初养成-2-10 Java中的强制类型转换
来源:http://www.imooc.com/code/1241 相信小伙伴们也发现了,尽管自动类型转换是很方便的,但并不能满足所有的编程需要. 例如,当程序中需要将 double 型变量的值赋给一 ...
- PERT(计划评审技术,Program Evaluation an Review Technique)
如果你对项目管理.系统架构有兴趣,请加微信订阅号"softjg",加入这个PM.架构师的大家庭 PERT(计划评审技术,Program Evaluation an Review T ...
- Java基础——IO流
今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理 ...
- VC与JavaScript交互(二) --- 调用JS函数
这一章,我们来动手实践VC调用JS函数. 我们动手写一个HTML,其中包含这样一段JS代码: //[html] <script type="text/javascript"& ...