
硬件层面接收到报文之后,做一系列的初始化 *** 作,之后驱动才开始把一个封包封装为skb。
当然这是在x86架构下,如果是在cavium架构下,封包是wqe形式存在。
不管是skb还是wqe,都仅仅是一种手段,一种达到完成报文传输所采用的一种解决方案,一种方法而已。
或许处理方案的具体实现细节差别万千,但是基本的原理,都是殊途同归,万变不离其宗。
skb的产生,让Linux协议栈旅程的开启,具备了最基本的条件,接下来的协议栈之旅,才会更加精彩。
写作本文的原因是现在本机网络 IO 应用非常广。
在 php 中 一般 nginx 和 php-fpm 是通过 127.0.0.1 来进行通信的;
在微服务中,由于 side car 模式的应用,本机网络请求更是越来越多。
所以,如果能深度理解这个问题在各种网络通信应用的技术实践中将非常的有意义。
今天咱们就把 127.0.0.1 本机网络通信相关问题搞搞清楚!
为了方便讨论,我把这个问题拆分成3问:
1)127.0.0.1 本机网络 IO 需要经过网卡吗?
2)和外网网络通信相比,在内核收发流程上有啥差别?
3)使用 127.0.0.1 能比 192.168.x.x 更快吗?
在上面这幅图中,我们看到用户数据被拷贝到内核态,然后经过协议栈处理后进入到了 RingBuffer 中。随后网卡驱动真正将数据发送了出去。当发送完成的时候,是通过硬中断来通知 CPU,然后清理 RingBuffer。
当数据包到达另外一台机器的时候,Linux 数据包的接收过程开始了。
当网卡收到数据以后,CPU发起一个中断,以通知 CPU 有数据到达。
当CPU收到中断请求后,会去调用网络驱动注册的中断处理函数,触发软中断。
ksoftirqd 检测到有软中断请求到达,开始轮询收包,收到后交由各级协议栈处理。
当协议栈处理完并把数据放到接收队列的之后,唤醒用户进程(假设是阻塞方式)。
关于跨机网络通信的理解,可以通俗地用下面这张图来总结一下:
前面,我们看到了跨机时整个网络数据的发送过程 。
在本机网络 IO 的过程中,流程会有一些差别。
为了突出重点,本节将不再介绍整体流程,而是只介绍和跨机逻辑不同的地方。
有差异的地方总共有两个,分别是路由和驱动程序。
对于本机网络 IO 来说,特殊之处在于在 local 路由表中就能找到路由项,对应的设备都将使用 loopback 网卡,也就是我们常见的 lO。
从上述结果可以看出,对于目的是 127.0.0.1 的路由在 local 路由表中就能够找到了。
对于是本机的网络请求,设备将全部都使用 lo 虚拟网卡,接下来的网络层仍然和跨机网络 IO 一样。
本机网络 IO 需要进行 IP 分片吗?
因为和正常的网络层处理过程一样,如果 skb 大于 MTU 的话,仍然会进行分片。
只不过 lo 的 MTU 比 Ethernet 要大很多。
通过 ifconfig 命令就可以查到,普通网卡一般为 1500,而 lO 虚拟接口能有 65535。
为什么我把“驱动”加个引号呢,因为 loopback 是一个纯软件性质的虚拟接口,并没有真正意义上的驱动。
在邻居子系统函数中经过处理,进入到网络设备子系统,只有触发完软中断,发送过程就算是完成了。
在跨机的网络包的接收过程中,需要经过硬中断,然后才能触发软中断。
而在本机的网络 IO 过程中,由于并不真的过网卡,所以网卡实际传输,硬中断就都省去了。直接从软中断开始,送进协议栈。
网络再往后依次是传输层,最后唤醒用户进程,这里就不多展开了。
我们来总结一下本机网络通信的内核执行流程:
回想下跨机网络 IO 的流程:
通过本文的叙述,我们确定地得出结论,不需要经过网卡。即使了把网卡拔了本机网络是否还可以正常使用的。
总的来说,本机网络 IO 和跨机 IO 比较起来,确实是节约了一些开销。发送数据不需要进 RingBuffer 的驱动队列,直接把 skb 传给接收协议栈(经过软中断)。
但是在内核其它组件上可是一点都没少:系统调用、协议栈(传输层、网络层等)、网络设备子系统、邻居子系统整个走了一个遍。连“驱动”程序都走了(虽然对于回环设备来说只是一个纯软件的虚拟出来的东东)。所以即使是本机网络 IO,也别误以为没啥开销。
先说结论:我认为这两种使用方法在性能上没有啥差别。
我觉得有相当大一部分人都会认为访问本机server 的话,用 127.0.0.1 更快。原因是直觉上认为访问 IP 就会经过网卡。
其实内核知道本机上所有的 IP,只要发现目的地址是本机 IP 就可以全走 loopback 回环设备了。
本机其它 IP 和 127.0.0.1 一样,也是不用过物理网卡的,所以访问它们性能开销基本一样!
How SKBs work - Linux kernel
http://vger.kernel.org/~davem/skb.html
一篇解读Linux网络协议栈
https://zhuanlan.zhihu.com/p/475319464
你真的了解127.0.0.1和0.0.0.0的区别?
http://www.52im.net/thread-2928-1-1.html
深入 *** 作系统,彻底搞懂127.0.0.1本机网络通信
http://www.52im.net/thread-3590-1-1.html
文件描述符概述文件描述符是非负整数,是文件的标识
用户使用文件描述符(file descriptor)来访问文件利用open打开一个文件时,内核会返回一个文件描述符
每个进程都有一张文件描述符的表,进程刚被创建时,标准输入,标准输出,标准错误输出设备文件被打开,对应的文件描述符0, 1, 2记录在表中
在进程中打开其他文件时,系统会返回文件描述符表中最小可用的文件描述符,并将此文件描述符记录在表中
注意:
linux中一个进程最多只能打开NR_OPEN_DEFAULT
(即1024)个文件,也就意味着最多能得到1024(0~1023)个文件描述符,故当文件不再使用时应及时调用close函数关闭文件
注意;新创建的文件描述符的值不一定是最大的
VMWare虚拟机软件是一个“虚拟PC”软件,它使你可以在一台机器上同时运行二个或更多Windows、DOS、LINUX系统。那你知道在VMware虚拟机里Linux系统怎么上网吗?我带来了VMware虚拟机里Linux系统上网的 方法 ,下面大家跟着我一起来学习一下吧。
VMware虚拟机里Linux系统上网方法参考如下
原理:使用Windows下的连接作为网关。Linux作为一个虚拟的客户端通过这个Windows下的连接连上网。
1、设置Windows下的本地连接允许VMware的虚拟网卡来共享上网。
2、设置Windows下的VMware产生的虚拟网卡1。将其IP设置为192.168.0.1。子网掩码为255.255.255.0。
3、设置VMware的网卡为Host-only
4、启动Linux,然后在网络设置中将eth0设置为IP为 192.168.0.2。然后设置子网掩码255.255.255.0。再设置网关为192.168.0.1。最后设置DNS为Windows下使用的那 个DNS地址即可(在安装虚拟机前可以用ipconfig查到)。再激活eth0即可。
5、如果不行,那就设置完后,重启你的电脑。
而我在公司装的时候,没做第3步,用了默认的NAT方式,同样也可以上网。
VMware的网卡设置模式
VMware 提供四种网络连接方式
Bridge:这种方式最简单,直接将虚拟网卡桥接到一个物理网卡上面,和linux下一个网卡 绑定两个不同地址类似,实际上是将网卡设置为混杂模式,从而达到侦听多个IP的能力.
在此种模式下,虚拟机内部的网卡(例如linux下的eth0)直接连到了物理网卡所在的网络上,可以想象为虚拟机和host机处于对等的地位,在网络关系上是平等的,没有谁在谁后面的问题.
使用这种方式很简单,前提是你可以得到1个以上的地址.对于想进行种种网络实验的朋友不太适合,因为你无法对虚拟机的网络进行控制,它直接出去了.
nat方式:这种方式下host内部出现了一个虚拟的网卡vmnet8(默认情况下),如果你有过做nat服务器的 经验 ,这里的vmnet8就相当于连接到内网的网卡,而虚拟机本身则相当于运行在内网上的机器,虚拟机内的网卡(eth0)则独立于vmnet8.
你会发现在这种方式下,vmware自带的dhcp会默认地加载到vmnet8界面上,这样虚拟机就可以使用dhcp服务.更为重要的 是,vmware自带了nat服务,提供了从vmnet8到外网的地址转 换,所以这种情况是一个实实在在的nat服务器在运行,只不过是供虚拟机用的. 很显然,如果你只有一个外网地址,此种方式很合适.
hostonly:
这应该是最为灵活的方式,有兴趣的话可以进行各种网络实验.和nat唯一的不同的是,此种方式下,没有地址转换服务,因此,默认情况下,虚拟机只 能到主机访问,这也是hostonly的名字的意义. 默认情况下,也会有一个dhcp服务加载到vmnet1上.这样连接到vmnet8上的虚拟机仍然可以设置成dhcp,方便系统的配置.
是不是这种方式就没有办法连接到外网呢,当然不是,事实上,这种方式更为灵活,你可以使用自己的方式,从而达到最理想的配置,例如:
a.使用自己dhcp服务:首先停掉vmware自带的dhcp服务,使dhcp服务更为统一.
b.使用自己的nat,方便加入防火墙.windows host可以做nat的方法很多,简单的如windows xp的internet共享,复杂的如windows server里的nat服务.
c. 使用自己的防火墙.因为你可以完全控制vmnet1,你可以加入(或试验)防火墙在vmnet1和外网的网卡间.
从以上可以看出,hostonly这种模式和普通的nat server带整个内网上网的情形类似,因此你可以方便的进行与之有关的实验,比如防火强的设置等
1、Bridge模式(一切都跟host一样,只有ip不能与host相同)
ip 192.168.39.222
netmask:255.255.252.0
gateway:192.168.39.254
Primary nameserve:192.168.39.252
2、NAT模式
首先在host中查看VMnet8的IP(e.g. 192.168.255.1).
启动VMware,点Edit下Virtual Network Setting… ,d出Virtual network Editor对话框
查看NAT选项卡,记录NAT的Gateway IP address:192.168.255.2
在config中,填写:
ip:192.168.255.5(与192.168.255.1在同一个网段的不同地址)
netmask:255.255.255.0(与192.168.255.1的隐码相同)
Gateway IP:填写VMware中的NAT网关192.168.255.2
Primary nameserver:填写与主机中一样的网关192.168.39.252,这样就可以上网冲浪了.
如果填写192.168.255.1,则不能连上外网.这里也可以不停,总之不能写错误的地址
3、hostonly模式
(1)查看你的连接外网的网卡的属性,选择“高级”标签,设置成允许共享,并设定允许的网络接口为VMNET1
(2)再插看一下你的VMnet1 的属性,看一下TCP/IP协议的设置,你发现已经被自动设置为
192.168.0.1/255.255.255.0,
(3)windows下的设置完成,转入到跑linux的虚拟机.将你的eth0的ip地址设置为静态的(如果安装时没有选静态的话) .
按红帽子图标->系统设置->网络(或 其它 你了解的方法)
ip: 192.168.0.2(或其它在此网段上的地址)
netmask: 255.255.255.0
default gateway: 192.168.0.1 (VMnet1的地址)
dns:输入你自己的DNS (host中用的DNS)
保存设置.如果你还没有设置好主机名称:
cd /etc/sysconfig
vi network
编辑HOSTNAME
cd /etc
vi hosts
加入:
192.168.0.2 yourhostname
重新启动服务
su
/sbin/service network restart
(4)测试一下
网关: ping 192.168.0.1
dns: ping dnsserver
(1)Bridged方式
用这种方式,虚拟系统的IP可设置成与本机系统在同一网段,虚拟系统相当于网络内的一台.独立的机器,与本机共同插在一个Hub上,网络内其他机器可访问虚拟系统,虚拟系统也可访问网络内其他机器,当然与本机系统的双向访问也不成问题.
(2)NAT方式
这种方式也可以实现本机系统与虚拟系统的双向访问.但网络内其他机器不能访问虚拟系统,虚拟系统可通过本机系统用NAT协议访问网络内其他机 器.NAT方式的IP地址配置方法:虚拟系统先用DHCP自动获得IP地址,本机系统里的VMware services会为虚拟系统分配一个IP,之后如果想每次启动都用固定IP的话,在虚拟系统里直接设定这个IP即可.
(3)host-only方式
顾名思义这种方式只能进行虚拟机和主机之间的网络通信,既网络内其他机器不能访问虚拟系统,虚拟系统也不能访问其他机器.
(4)not use方式
既是不使用网络,虚拟系统为一个单机.
一般来说,Bridged方式最方便好用.但如果本机系统是win2000而网线没插(或者根本没有网卡),网络很可能不可用(大部分用PCI网卡的机器都如此),此时就只能用NAT方式或host-only,之前所说的那两块虚拟网卡就是适应这两种网络准备的.
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)