Es ist eine Geschichte, dass der Befehl netstat schneller wurde, wenn der Linux-Kernel und der Befehl netstat leicht modifiziert wurden.
/ proc / net / tcp
, um Informationen zu TCP-Sitzungen vom Kernel abzurufen.man 2 read
usw. für die Argumente des Systemaufrufs read./ proc / net / tcp
mehrere MiByte betragen, der Aufruf des Lesesystems kann jedoch nur Daten mit einer Kapazität von 4096Byte oder weniger lesen und / Hunderte von gelesenen Systemaufrufen müssen ausgeführt werden, um den gesamten Inhalt von proc / net / tcp
zu lesen/ proc / net / tcp
eine TCP-Sitzung = 1 Zeile 150 Byte beträgt und 10.000 Sitzungen abgehalten werden (einschließlich TIME_WAIT), beträgt die Dateigröße etwa 1,5 MByte und der Systemaufruf zum Lesen beträgt 300. Wird mehr als einmal ausgeführt
―― Tatsächlich wird die Anzahl der Male weiter erhöht, da sie für jede Zeile auf eine gut getrennte Kapazität gerundet wird und nur etwas weniger als 4096 Bytes gelesen werden können./ proc / net / tcp
verarbeitet, im Linux-Kernel und den Befehl netstat ändern, um die Datenmenge zu erhöhen, die von einem gelesenen Systemaufruf gelesen wird, verringert sich die Anzahl der gelesenen Systemaufrufe. Und der Befehl netstat ist schneller$ uname -r
3.10.0-693.17.1.el7.x86_64
$ rpm -q kernel
kernel-3.10.0-693.11.6.el7.x86_64
kernel-3.10.0-693.17.1.el7.x86_64
$ rpm -q net-tools
net-tools-2.0-0.22.20131004git.el7.x86_64
$ cat /etc/redhat-release
CentOS Linux release 7.4.1708 (Core)
$ LANG=C lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 2
On-line CPU(s) list: 0,1
Thread(s) per core: 2
Core(s) per socket: 1
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 63
Model name: Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz
Stepping: 2
CPU MHz: 2394.456
BogoMIPS: 4788.91
Virtualization: VT-x
Hypervisor vendor: Microsoft
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 30720K
NUMA node0 CPU(s): 0,1
Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq vmx ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm tpr_shadow vnmi ept vpid fsgsbase bmi1 avx2 smep bmi2 erms xsaveopt
$ free -m
total used free shared buff/cache available
Mem: 7966 416 6876 8 673 7205
Swap: 0 0 0
--Installieren und konfigurieren Sie verschiedene Elemente, die zum Erstellen des RPM-Pakets erforderlich sind
sudo useradd mockbuild
sudo yum -y install rpm-build
sudo yum -y groups install "Development Tools"
yumdownloader --source kernel
rpm -ivh kernel-3.10.0-693.17.1.el7.centos.plus.src.rpm
sudo yum -y install m4 gcc xmlto asciidoc hmaccalc python-devel newt-devel 'perl(ExtUtils::Embed)' pesign elfutils-devel zlib-devel binutils-devel bison audit-libs-devel java-devel openssl-devel numactl-devel pciutils-devel ncurses-devel
--Erstellen Sie einen Patch mit dem folgenden Inhalt als "~ / rpmbuild / SOURCES / proc-net-tcp.patch"
--- a/net/ipv4/tcp_ipv4.c 2018-01-14 15:02:54.000000000 +0000
+++ b/net/ipv4/tcp_ipv4.c 2018-02-10 06:08:39.043951339 +0000
@@ -2382,10 +2382,21 @@
return 0;
}
+static ssize_t tcp_seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+ struct seq_file *m = file->private_data;
+ if (!m->buf) {
+ m->buf = kmalloc( m->size = 16 * PAGE_SIZE, GFP_KERNEL);
+ if (!m->buf)
+ return -ENOMEM;
+ }
+ return seq_read(file, buf, size, ppos);
+}
+
static const struct file_operations tcp_afinfo_seq_fops = {
.owner = THIS_MODULE,
.open = tcp_seq_open,
- .read = seq_read,
+ .read = tcp_seq_read,
.llseek = seq_lseek,
.release = seq_release_net
};
--- a/net/ipv6/tcp_ipv6.c 2018-01-14 15:02:54.000000000 +0000
+++ b/net/ipv6/tcp_ipv6.c 2018-02-10 06:10:39.910935928 +0000
@@ -1812,10 +1812,21 @@
return 0;
}
+static ssize_t tcp_seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
+{
+ struct seq_file *m = file->private_data;
+ if (!m->buf) {
+ m->buf = kmalloc( m->size = 16 * PAGE_SIZE, GFP_KERNEL);
+ if (!m->buf)
+ return -ENOMEM;
+ }
+ return seq_read(file, buf, size, ppos);
+}
+
static const struct file_operations tcp6_afinfo_seq_fops = {
.owner = THIS_MODULE,
.open = tcp_seq_open,
- .read = seq_read,
+ .read = tcp_seq_read,
.llseek = seq_lseek,
.release = seq_release_net
};
$ diff ~/rpmbuild/SPECS/kernel.spec.org ~/rpmbuild/SPECS/kernel.spec
8c8
< %define buildid .centos.plus
---
> %define buildid .procnettcp
463a464,465
> Patch50000: proc-net-tcp.patch
>
832a835,836
>
> ApplyPatch proc-net-tcp.patch
――Die in der diesmal verwendeten Umgebung benötigte Zeit beträgt mehr als 1,5 Stunden
rpmbuild -ba ~/rpmbuild/SPECS/kernel.spec
find ~/rpmbuild/ -name "*.rpm"
/ proc / net / tcp
lesen.--Für den Befehl cat, der den Inhalt von / proc / net / tcp
liest, verwenden Sie den Befehl strace, um den Status des Aufrufs des gelesenen Systems zu beobachten.
$ uname -r
3.10.0-693.17.1.el7.procnettcp.x86_64
$ LANG=C strace -e open,read cat /proc/net/tcp|wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY) = 3
read(3, " sl local_address rem_address "..., 65536) = 11700
read(3, "", 65536) = 0
78
+++ exited with 0 +++
$ uname -r
3.10.0-693.17.1.el7.x86_64
$ LANG=C strace -e open,read cat /proc/net/tcp|wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY) = 3
read(3, " sl local_address rem_address "..., 65536) = 4050
read(3, " 26: 0502010A:861A 10813FA8:005"..., 65536) = 1650
read(3, "", 65536) = 0
38
+++ exited with 0 +++
$ uname -r
3.10.0-693.17.1.el7.procnettcp.x86_64
$ LANG=C strace -e open,read netstat -atn |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY) = 3
read(3, " sl local_address rem_address "..., 4096) = 4096
read(3, "00000000 03:00001608 00000000 "..., 4096) = 4096
read(3, " 3 ffff880287e55d00 "..., 4096) = 4096
read(3, " \n", 4096) = 12
read(3, "", 4096) = 0
open("/proc/net/tcp6", O_RDONLY) = 3
read(3, " sl local_address "..., 4096) = 853
read(3, "", 4096) = 0
+++ exited with 0 +++
87
$ uname -r
3.10.0-693.17.1.el7.x86_64
$ LANG=C strace -e open,read netstat -atn |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY) = 3
read(3, " sl local_address rem_address "..., 4096) = 4050
read(3, " 26: 0502010A:870C 10813FA8:005"..., 4096) = 4050
read(3, " 53: 0502010A:E488 19E57328:01B"..., 4096) = 900
read(3, "", 4096) = 0
open("/proc/net/tcp6", O_RDONLY) = 3
read(3, " sl local_address "..., 4096) = 676
read(3, "", 4096) = 0
+++ exited with 0 +++
64
yumdownloader --source net-tools
rpm -ivh net-tools-2.0-0.22.20131004git.el7.src.rpm
sudo yum -y install libselinux-devel
--Erstellen Sie einen Patch mit dem folgenden Inhalt als "~ / rpmbuild / SOURCES / net-tools-netstat-proc-net-tcp-buffer-size.patch"
--- a/lib/proc.c 2013-09-30 08:07:32.000000000 +0000
+++ b/lib/proc.c 2018-02-11 04:48:40.959339035 +0000
@@ -88,9 +88,9 @@
if (!buffer) {
pagesz = getpagesize();
- buffer = malloc(pagesz);
+ buffer = malloc(16*pagesz);
}
- setvbuf(fd, buffer, _IOFBF, pagesz);
+ setvbuf(fd, buffer, _IOFBF, 16*pagesz);
return fd;
}
$ diff ~/rpmbuild/SPECS/net-tools.spec.org ~/rpmbuild/SPECS/net-tools.spec
67a68,69
> Patch100: net-tools-netstat-proc-net-tcp-buffer-size.patch
>
104a107,108
>
> %patch100 -p1 -b .proc-net-tcp
rpmbuild -bb ~/rpmbuild/SPECS/net-tools.spec
ls -l ~/rpmbuild/BUILD/net-tools/netstat
/ proc / net / tcp
um 4096 Bytes gelesen.$ LANG=C strace -e open,read netstat -atn |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY) = 3
read(3, " sl local_address rem_address "..., 4096) = 4096
read(3, "00000000 03:0000022B 00000000 "..., 4096) = 4096
read(3, " 3 ffff8802c43a7d00 "..., 4096) = 3508
read(3, "", 4096) = 0
open("/proc/net/tcp6", O_RDONLY) = 3
read(3, " sl local_address "..., 4096) = 853
read(3, "", 4096) = 0
+++ exited with 0 +++
83
$ LANG=C strace -e open,read ~/rpmbuild/BUILD/net-tools-2.0/netstat -atn |wc -l
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300j\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\35\2\0\0\0\0\0"..., 832) = 832
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360\25\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\16\0\0\0\0\0\0"..., 832) = 832
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0m\0\0\0\0\0\0"..., 832) = 832
open("/proc/net/tcp", O_RDONLY) = 3
read(3, " sl local_address rem_address "..., 65536) = 11700
read(3, "", 65536) = 0
open("/proc/net/tcp6", O_RDONLY) = 3
read(3, " sl local_address "..., 65536) = 853
read(3, "", 65536) = 0
+++ exited with 0 +++
83
--Verwenden Sie Apache und den Befehl ab des mit Apache gelieferten Benchmark-Tools, um die Anzahl der TCP-Sitzungen zu erhöhen --Vergleichen Sie die Operation des Befehls netstat vor und nach der Änderung, während Sie den Einzeiler ausführen, der Apache installiert und startet und den Befehl ab wiederholt ausführt.
sudo yum -y install httpd
sudo systemctl start httpd.service
while : ; do ab -n 100000 -c 1000 127.0.0.1/test; done
$ time netstat -atn |wc -l
16528
real 0m0.355s
user 0m0.110s
sys 0m0.254s
$ time ~/rpmbuild/BUILD/net-tools-2.0/netstat -atn |wc -l
16202
real 0m0.133s
user 0m0.115s
sys 0m0.027s
/ proc / net / tcp
(verwendet einen speziellen Socket". Die Anzahl der TCP-Sitzungen wird von netlink ") erfasst und kann schneller als der oben geänderte Befehl netstat verarbeitet werden.[^ ss-using-procfs]: Wenn die Erfassung von Informationen durch Netlink fehlschlägt, werden die Informationen mithilfe von procfs erfasst.
$ time ss -atn |wc -l
15922
real 0m0.046s
user 0m0.033s
sys 0m0.021s
In Anbetracht dessen, dass der Befehl netstat oder die net-tools als veraltet angesehen werden, ist es besser, den Befehl ss gehorsam zu verwenden.
Recommended Posts