netstat –help
netstat -anltu
netstat -anplt
netstat –nplt
netstat -tnpl
| netstat -atun | grep 被测试机器的IP地址 |
-a 显式所有的socket
linux下进程、端口号相互查看方法
https://www.cnblogs.com/MacoLee/p/5664306.html
| ps -ef | grep 进程名 |
| netstat -nap | grep 进程pid |
linux通过端口查看进程:
| netstat -nap | grep 端口号 |
查看网卡的丢包记录
netstat -i
输出中的 RX-OK、RX-ERR、RX-DRP、RX-OVR ,分别表示接收时的总包数、总错误数、进入Ring Buffer 后因其他原因(如内存不足)导致的丢包数以及 Ring Buffer 溢出导致的丢包数。
TX-OK、TX-ERR、TX-DRP、TX-OVR 也代表类似的含义,只不过是指发送时对应的各个指标。
ARP协议(地址解析协议)属于数据链路层的协议,主要负责根据网络层地址(IP)来获取数据链路层地址(MAC)。
借助Scapy来编写ARP主机发现脚本,通过脚本对以太网内的每个主机都进行ARP请求。若主机存活,则会响应我们的ARP请求,否则不会响应。
Scapy中的ARP参数如下所示:

op代表消息类型:1为ARP请求,2为ARP响应 hwsrc代表源MAC地址 psrc代表源IP地址 hwdst代表目的MAC地址 pdst代表目的IP地址
Scapy中的Ether参数如下所示:

src表示源MAC地址
dst表示目的MAC地址
#!/usr/bin/python3
#-*- coding: utf-8 -*-
import os
import re
import optparse
from scapy.all import *
#取IP地址和MAC地址获取函数
def HostAddress(iface):
#os.popen执行后返回执行结果
ipData = os.popen('ifconfig '+iface)
#对ipData进行类型转换,再用正则进行匹配
dataLine = ipData.readlines()
#re.search利用正则匹配返回第一个成功匹配的结果,存在结果则为true
#取MAC地址
global MAC
global IP
if re.search('\w\w:\w\w:\w\w:\w\w:\w\w:\w\w',str(dataLine)):
#取出匹配的结果
MAC = re.search('\w\w:\w\w:\w\w:\w\w:\w\w:\w\w',str(dataLine)).group(0)
#取IP地址
if re.search(r'((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)',str(dataLine)):
IP = re.search(r'((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)',str(dataLine)).group(0)
#将IP和MAC通过元组的形式返回
addressInfo = (IP,MAC)
return addressInfo
#ARP扫描函数
def ArpScan(iface='eth0'):
# 通过HostAddres返回的元组取出MAC地址
mac = HostAddress(iface)[1]
#取出本机IP地址
ip = HostAddress(iface)[0]
#对本机IP地址进行分割并作为依据元素,用于生成需要扫描的IP地址
ipSplit = ip.split('.')
#需要扫描的IP地址列表
ipList = []
for i in range(1,255):
ipItem = ipSplit[0] + '.' + ipSplit[1] + '.' + ipSplit[2] + '.' + str(i)
ipList.append(ipItem)
'''
发送ARP包
因为要用到OSI的二层和三层,所以要写成Ether/ARP。
因为最底层用到了二层,所以要用srp()发包
'''
result=srp(Ether(src=mac,dst='FF:FF:FF:FF:FF:FF')/ARP(op=1,hwsrc=mac,hwdst='00:00:00:00:00:00',pdst=ipList),iface=iface,timeout=2,verbose=False)
#读取result中的应答包和应答包内容
resultAns = result[0].res
#存活主机列表
liveHost = []
#number为接收到应答包的总数
number = len(resultAns)
print("=========================")
print("ARP 探测结果")
print("本机IP地址:" + ip)
print("本机MAC地址:" + mac)
print("=========================")
for x in range(number):
IP = resultAns[x][1][1].fields['psrc']
MAC = resultAns[x][1][1].fields['hwsrc']
liveHost.append([IP,MAC])
print("IP:" + IP + "\n\n" + "MAC:" + MAC )
print("============================")
# 把存活主机IP写入文件
resultFile = open("result","w")
for i in range(len(liveHost)):
resultFile.write(liveHost[i][0] + "\n")
resultFile.close()
if __name__ == '__main__':
parser = optparse.OptionParser('usage: python %prog -i interfaces \n\n' 'Example: python %prog -i eth0\n')
#添加网卡参数 -i
parser.add_option('-i','--iface',dest='iface',default='eth0',type='string', help='interfaces name')
(options,args) = parser.parse_args()
ArpScan(options.iface)
脚本测试结果如下:

查看结果文件如下所示:

1、使用原生的开源工具Valgrind,可以参考官网:http://www.valgrind.org/
2、现主要使用该工具检测以下问题:
(1)写越界导致的踩内存问题
(2)内存free后仍在使用的问题
(3)错误使用未初始化内存
Valgrind是一套Linux下,开放源代码(GPL V2)的仿真调试工具的集合。Valgrind由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个CPU环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。
Valgrind允许用户分析(profile)和调试Linux上的可执行程序。
Valgrind包含的内存检查工具Memcheck可以检测常见的内存错误。此类错误包括访问无效的内存,使用未初始化的值,不正确的释放内存,以及内存泄漏。然而,Memcheck不对静态数组的边界进行检查。
内存泄漏可以允许攻击者在受影响的程序上进行拒绝服务。
https://zhuanlan.zhihu.com/p/342958592 内存错误修复指南
Socket是计算机之间进行网络通信的一套程序接口,相当于在发送端和接收端之间建立了一个通信管道。在实际应用中,一些远程管理软件和网络安全软件大多依赖于Socket来实现特定功能,由于TCP(Transmission Control Protocol,传输控制协议)方式在网络编程中应用得非常频繁,此处给出具体应用实例。 编写TCP时一般会用到的Socket模块,其方法主要包括:
·connect(address):连接远程计算机
·send(bytes[,flags]):发送数据
·recv(bufsize[,flags]):接收数据
·bind(address):绑定地址
·listen(backlog):开始监听,等待客户端连接
·accept():响应客户端的一个请求,接受一个连接
使用TCP进行通信,首先需要在客户端和服务端建立连接,并且要在通信结束后关闭连接以释放资源。由于TCP是面向连接的,因此相对于UDP提供更高的可靠性。
Demo: 设计一个对话系统。该应用分为两个部分,一部分为服务端,一部分为客户端。客户端发送请求信息,服务端返回应答信息。两部分代码如下所示。
(1)服务端代码 server.py
# coding=UTF-8
import socket
language = {'what is your name':'I am Tom','how old are you':'25','bye':'bye!'}
HOST = "127.0.0.1"
PORT = 6666
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((HOST,PORT))
s.listen(1)
print("Listing at port 6666")
conn,addr = s.accept()
print('Connect by:', addr)
while True:
data = conn.recv(1024)
data = data.decode()
if not data:
break
print('Received message:', data)
conn.sendall(language.get(data,'Nothing').encode())
conn.close()
s.close()
(2)客户端代码 client.py
# coding=UTF-8
import socket,sys
HOST = "127.0.0.1"
PORT = 6666
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
s.connect((HOST,PORT))
except Exception as e:
print('server not found!')
sys.exit()
while True:
c = input('YOU SAY:')
s.sendall(c.encode())
data = s.recv(1024)
data = data.decode()
print('Received:',data)
if c.lower()=='再见':
break
在一个窗口运行服务端程序,服务端开始进行监听;启动一个新的窗口并运行客户端程序,服务端程序提示连接已建立;在客户端输入要发送的信息后,服务端会根据提前建立的字典进行自动回复。对话效果,如图所示:




SPDK是由英特尔发起的,用于加速NVMe SSD作为后端存储使用的应用软件加速库。这个软件库的核心是用户态,异步,轮询方式的NVMe驱动。相比内核的NVMe驱动,SPDK可以大幅降低NVMe command的延迟,提高单CPU核的IOPS,形成一套高性价比的解决方案,如SPDK的vhost解决方案可以被应用到HCI中加速虚拟机的NVMe I/O。
SPDK的核心组件之一就是用户态NVMe驱动。
用户态驱动出现的目的就是减少软件本身的开销,包括这里所说的上下文切换,系统调用等。在用户态目前可以通过UIO(Userspace I/O)或VFIO(Virtual Function I/O)两种方式对硬件固态硬盘设备进行访问。 大页(Hugepage),通过使用HugePage分配大页可以提高性能。因为页大小的增加,可以减少缺页异常。例如,2MB大小的内容(假设是2MB对齐),如果是4KB大小的页粒度,则会产生512次缺页异常,但是使用2MB大小的页,只会产生一次缺页异常。大页的缺点:需要额外配置,需要应用程序事先预估使用多少内存,大页需要在进程启动之前实现启用和分配好内存。
Linux内核NVMe驱动和SPDK NVMe驱动实现的区别:
| 功能比较 | 内核NVMe驱动 | SPDK NVMe驱动 |
|---|---|---|
| 工作模式 | 中断 | 异步轮询方式 |
| I/O路径是否需要同步 | CPU之间需要同步 | CPU之间以无锁方式运行 |
| 是否需要系统调用 | 需要 | 不需要,直接通过 |
| I/O内存页管理 | DMA内存页映射 | 大页,通过hugetlbfs |
| 块设备支持 | 通过内核通用块设备层 | 专门为Flash优化(此外SPDK也提供用户态块设备层) |
1)异步轮询方式 SPDK用户态驱动对设备完成状态的检测,是通过异步轮询的方式来实现的,进而避免了对中断的依赖。轮询到操作完成时会触发上层的回调函数,这样使得应用程序无须等待读或写操作的完成,就可以按需发送多个请求,再由回调函数处理。由此来提高应用的读/写性能。
2)无锁化 在数据通道上去掉对锁的依赖。这里主要考虑以下问题。 ·读/写处理要在一个CPU核上完成,避免核间的缓存同步(可以通过线程亲和性的方法,将某个处理线程绑定到某个特定的核上。同时通过轮询的方式占住该核的使用,避免操作系统调度其他的线程到该核上面) ·单核上的处理,对资源的分配是无锁化的。(mempool,无锁队列,环)
3)专门为Flash来优化 通过UIO或VFIO把PCI设备的BAR(Base Address Register)地址映射到应用进程的空间,这样SPDK用户态驱动就可以遵循NVMe的规范来初始化NVMe SSD,创建出最基本的I/O发送和完成队列,最终实现对NVMe SSD设备的I/O读或写操作。

最下层为驱动层,中间层为通用块层,最上层为存储协议层。
SPDK是专门为NVMe开发的用户空间驱动,放弃原有系统调用模式,是基于以下两个原因:
(1)NVMe设备的IOPS很高,如果按照传统的系统调用,需要先从内核空间返回用户空间,这些开销对NVMe而言就比较大了;
(2)内核块层是通用的,而作为存储产品这些设备是专用的,不需要传统的I/O调度器。
创池前,nvme盘在内核态;创池后,nvme盘被spdk纳管为用户态。
(modprobe命令用于智能地向内核中加载模块或者从内核中移除模块。 modprobe可载入指定的个别模块,或是载入一组相依的模块。)
nvme.conf.in 该文件存在则代表SPDK已经生效,不存在则代表未生效。
install_spdk.sh
spdk_setup.sh
https://www.intel.cn/content/www/cn/zh/developer/articles/tool/introduction-to-the-storage-performance-development-kit-spdk.html
https://www.cnblogs.com/whl320124/articles/9969395.html
https://github.com/spdk/spdk
https://rootw.github.io/2018/05/SPDK-all/